<?php
/**
 * Yii bootstrap file.
 *
 * This file is automatically generated using 'build lite' command.
 * It is the result of merging commonly used Yii class files with
 * comments and trace statements removed away.
 *
 * By using this file instead of yii.php, an Yii application may
 * improve performance due to the reduction of PHP parsing time.
 * The performance improvement is especially obvious when PHP APC extension
 * is enabled.
 *
 * DO NOT modify this file manually.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright &copy; 2008-2009 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * @version $Id: yiilite.php 1578 2009-12-13 04:37:05Z qiang.xue $
 * @since 1.0
 */


defined('YII_BEGIN_TIME') or define('YII_BEGIN_TIME',microtime(true));
defined('YII_DEBUG') or define('YII_DEBUG',false);
defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',0);
defined('YII_ENABLE_EXCEPTION_HANDLER') or define('YII_ENABLE_EXCEPTION_HANDLER',true);
defined('YII_ENABLE_ERROR_HANDLER') or define('YII_ENABLE_ERROR_HANDLER',true);
defined('YII_PATH') or define('YII_PATH',dirname(__FILE__));
class YiiBase
{
	private static $_aliases=array('system'=>YII_PATH); // alias => path
	private static $_imports=array();					// alias => class name or directory
	private static $_classes=array();
	private static $_includePaths;						// list of include paths
	private static $_app;
	private static $_logger;
	public static function getVersion()
	{
		return '1.0.11';
	}
	public static function createWebApplication($config=null)
	{
		return self::createApplication('CWebApplication',$config);
	}
	public static function createConsoleApplication($config=null)
	{
		return self::createApplication('CConsoleApplication',$config);
	}
	public static function createApplication($class,$config=null)
	{
		return new $class($config);
	}
	public static function app()
	{
		return self::$_app;
	}
	public static function setApplication($app)
	{
		if(self::$_app===null || $app===null)
			self::$_app=$app;
		else
			throw new CException(Yii::t('yii','Yii application can only be created once.'));
	}
	public static function getFrameworkPath()
	{
		return YII_PATH;
	}
	public static function createComponent($config)
	{
		if(is_string($config))
		{
			$type=$config;
			$config=array();
		}
		else if(isset($config['class']))
		{
			$type=$config['class'];
			unset($config['class']);
		}
		else
			throw new CException(Yii::t('yii','Object configuration must be an array containing a "class" element.'));
		if(!class_exists($type,false))
			$type=Yii::import($type,true);
		if(($n=func_num_args())>1)
		{
			$args=func_get_args();
			if($n===2)
				$object=new $type($args[1]);
			else if($n===3)
				$object=new $type($args[1],$args[2]);
			else if($n===4)
				$object=new $type($args[1],$args[2],$args[3]);
			else
			{
				unset($args[0]);
				$class=new ReflectionClass($type);
				// Note: ReflectionClass::newInstanceArgs() is available for PHP 5.1.3+
				// $object=$class->newInstanceArgs($args);
				$object=call_user_func_array(array($class,'newInstance'),$args);
			}
		}
		else
			$object=new $type;
		foreach($config as $key=>$value)
			$object->$key=$value;
		return $object;
	}
	public static function import($alias,$forceInclude=false)
	{
		if(isset(self::$_imports[$alias]))  // previously imported
			return self::$_imports[$alias];
		if(class_exists($alias,false) || interface_exists($alias,false))
			return self::$_imports[$alias]=$alias;
		if(isset(self::$_coreClasses[$alias]) || ($pos=strrpos($alias,'.'))===false)  // a simple class name
		{
			self::$_imports[$alias]=$alias;
			if($forceInclude)
			{
				if(isset(self::$_coreClasses[$alias])) // a core class
					require(YII_PATH.self::$_coreClasses[$alias]);
				else
					require($alias.'.php');
			}
			return $alias;
		}
		if(($className=(string)substr($alias,$pos+1))!=='*' && (class_exists($className,false) || interface_exists($className,false)))
			return self::$_imports[$alias]=$className;
		if(($path=self::getPathOfAlias($alias))!==false)
		{
			if($className!=='*')
			{
				self::$_imports[$alias]=$className;
				if($forceInclude)
					require($path.'.php');
				else
					self::$_classes[$className]=$path.'.php';
				return $className;
			}
			else  // a directory
			{
				if(self::$_includePaths===null)
				{
					self::$_includePaths=array_unique(explode(PATH_SEPARATOR,get_include_path()));
					if(($pos=array_search('.',self::$_includePaths,true))!==false)
						unset(self::$_includePaths[$pos]);
				}
				array_unshift(self::$_includePaths,$path);
				if(set_include_path('.'.PATH_SEPARATOR.implode(PATH_SEPARATOR,self::$_includePaths))===false)
					throw new CException(Yii::t('yii','Unable to import "{alias}". Please check your server configuration to make sure you are allowed to change PHP include_path.',array('{alias}'=>$alias)));
				return self::$_imports[$alias]=$path;
			}
		}
		else
			throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory or file.',
				array('{alias}'=>$alias)));
	}
	public static function getPathOfAlias($alias)
	{
		if(isset(self::$_aliases[$alias]))
			return self::$_aliases[$alias];
		else if(($pos=strpos($alias,'.'))!==false)
		{
			$rootAlias=substr($alias,0,$pos);
			if(isset(self::$_aliases[$rootAlias]))
				return self::$_aliases[$alias]=rtrim(self::$_aliases[$rootAlias].DIRECTORY_SEPARATOR.str_replace('.',DIRECTORY_SEPARATOR,substr($alias,$pos+1)),'*'.DIRECTORY_SEPARATOR);
			else if(self::$_app instanceof CWebApplication)
			{
				if(self::$_app->findModule($rootAlias)!==null)
					return self::getPathOfAlias($alias);
			}
		}
		return false;
	}
	public static function setPathOfAlias($alias,$path)
	{
		if(empty($path))
			unset(self::$_aliases[$alias]);
		else
			self::$_aliases[$alias]=rtrim($path,'\\/');
	}
	public static function autoload($className)
	{
		// use include so that the error PHP file may appear
		if(isset(self::$_coreClasses[$className]))
			include(YII_PATH.self::$_coreClasses[$className]);
		else if(isset(self::$_classes[$className]))
			include(self::$_classes[$className]);
		else
		{
			include($className.'.php');
			return class_exists($className,false) || interface_exists($className,false);
		}
		return true;
	}
	public static function trace($msg,$category='application')
	{
		if(YII_DEBUG)
		{
			if(YII_TRACE_LEVEL>0)
			{
				$traces=debug_backtrace();
				$count=0;
				foreach($traces as $trace)
				{
					if(isset($trace['file'],$trace['line']))
					{
						$className=substr(basename($trace['file']),0,-4);
						if(!isset(self::$_coreClasses[$className]) && $className!=='YiiBase')
						{
							$msg.="\nin ".$trace['file'].' ('.$trace['line'].')';
							if(++$count>=YII_TRACE_LEVEL)
								break;
						}
					}
				}
			}
			self::log($msg,CLogger::LEVEL_TRACE,$category);
		}
	}
	public static function log($msg,$level=CLogger::LEVEL_INFO,$category='application')
	{
		if(self::$_logger===null)
			self::$_logger=new CLogger;
		self::$_logger->log($msg,$level,$category);
	}
	public static function beginProfile($token,$category='application')
	{
		self::log('begin:'.$token,CLogger::LEVEL_PROFILE,$category);
	}
	public static function endProfile($token,$category='application')
	{
		self::log('end:'.$token,CLogger::LEVEL_PROFILE,$category);
	}
	public static function getLogger()
	{
		if(self::$_logger!==null)
			return self::$_logger;
		else
			return self::$_logger=new CLogger;
	}
	public static function powered()
	{
		return 'Powered by <a href="http://www.yiiframework.com/" target="_blank">Yii Framework</a>.';
	}
	public static function t($category,$message,$params=array(),$source=null,$language=null)
	{
		if(self::$_app!==null)
		{
			if($source===null)
				$source=$category==='yii'?'coreMessages':'messages';
			if(($source=self::$_app->getComponent($source))!==null)
				$message=$source->translate($category,$message,$language);
		}
		if($params===array())
			return $message;
		if(isset($params[0])) // number choice
		{
			$message=CChoiceFormat::format($message,$params[0]);
			unset($params[0]);
		}
		return $params!==array() ? strtr($message,$params) : $message;
	}
	public static function registerAutoloader($callback)
	{
		spl_autoload_unregister(array('YiiBase','autoload'));
		spl_autoload_register($callback);
		spl_autoload_register(array('YiiBase','autoload'));
	}
	private static $_coreClasses=array(
		'CApplication' => '/base/CApplication.php',
		'CApplicationComponent' => '/base/CApplicationComponent.php',
		'CBehavior' => '/base/CBehavior.php',
		'CComponent' => '/base/CComponent.php',
		'CErrorEvent' => '/base/CErrorEvent.php',
		'CErrorHandler' => '/base/CErrorHandler.php',
		'CException' => '/base/CException.php',
		'CExceptionEvent' => '/base/CExceptionEvent.php',
		'CHttpException' => '/base/CHttpException.php',
		'CModel' => '/base/CModel.php',
		'CModelBehavior' => '/base/CModelBehavior.php',
		'CModelEvent' => '/base/CModelEvent.php',
		'CModule' => '/base/CModule.php',
		'CSecurityManager' => '/base/CSecurityManager.php',
		'CStatePersister' => '/base/CStatePersister.php',
		'CApcCache' => '/caching/CApcCache.php',
		'CCache' => '/caching/CCache.php',
		'CDbCache' => '/caching/CDbCache.php',
		'CDummyCache' => '/caching/CDummyCache.php',
		'CEAcceleratorCache' => '/caching/CEAcceleratorCache.php',
		'CFileCache' => '/caching/CFileCache.php',
		'CMemCache' => '/caching/CMemCache.php',
		'CXCache' => '/caching/CXCache.php',
		'CZendDataCache' => '/caching/CZendDataCache.php',
		'CCacheDependency' => '/caching/dependencies/CCacheDependency.php',
		'CChainedCacheDependency' => '/caching/dependencies/CChainedCacheDependency.php',
		'CDbCacheDependency' => '/caching/dependencies/CDbCacheDependency.php',
		'CDirectoryCacheDependency' => '/caching/dependencies/CDirectoryCacheDependency.php',
		'CExpressionDependency' => '/caching/dependencies/CExpressionDependency.php',
		'CFileCacheDependency' => '/caching/dependencies/CFileCacheDependency.php',
		'CGlobalStateCacheDependency' => '/caching/dependencies/CGlobalStateCacheDependency.php',
		'CAttributeCollection' => '/collections/CAttributeCollection.php',
		'CConfiguration' => '/collections/CConfiguration.php',
		'CList' => '/collections/CList.php',
		'CListIterator' => '/collections/CListIterator.php',
		'CMap' => '/collections/CMap.php',
		'CMapIterator' => '/collections/CMapIterator.php',
		'CQueue' => '/collections/CQueue.php',
		'CQueueIterator' => '/collections/CQueueIterator.php',
		'CStack' => '/collections/CStack.php',
		'CStackIterator' => '/collections/CStackIterator.php',
		'CTypedList' => '/collections/CTypedList.php',
		'CConsoleApplication' => '/console/CConsoleApplication.php',
		'CConsoleCommand' => '/console/CConsoleCommand.php',
		'CConsoleCommandRunner' => '/console/CConsoleCommandRunner.php',
		'CHelpCommand' => '/console/CHelpCommand.php',
		'CDbCommand' => '/db/CDbCommand.php',
		'CDbConnection' => '/db/CDbConnection.php',
		'CDbDataReader' => '/db/CDbDataReader.php',
		'CDbException' => '/db/CDbException.php',
		'CDbTransaction' => '/db/CDbTransaction.php',
		'CActiveFinder' => '/db/ar/CActiveFinder.php',
		'CActiveRecord' => '/db/ar/CActiveRecord.php',
		'CActiveRecordBehavior' => '/db/ar/CActiveRecordBehavior.php',
		'CDbColumnSchema' => '/db/schema/CDbColumnSchema.php',
		'CDbCommandBuilder' => '/db/schema/CDbCommandBuilder.php',
		'CDbCriteria' => '/db/schema/CDbCriteria.php',
		'CDbExpression' => '/db/schema/CDbExpression.php',
		'CDbSchema' => '/db/schema/CDbSchema.php',
		'CDbTableSchema' => '/db/schema/CDbTableSchema.php',
		'CMssqlColumnSchema' => '/db/schema/mssql/CMssqlColumnSchema.php',
		'CMssqlCommandBuilder' => '/db/schema/mssql/CMssqlCommandBuilder.php',
		'CMssqlPdoAdapter' => '/db/schema/mssql/CMssqlPdoAdapter.php',
		'CMssqlSchema' => '/db/schema/mssql/CMssqlSchema.php',
		'CMssqlTableSchema' => '/db/schema/mssql/CMssqlTableSchema.php',
		'CMysqlColumnSchema' => '/db/schema/mysql/CMysqlColumnSchema.php',
		'CMysqlSchema' => '/db/schema/mysql/CMysqlSchema.php',
		'CMysqlTableSchema' => '/db/schema/mysql/CMysqlTableSchema.php',
		'COciColumnSchema' => '/db/schema/oci/COciColumnSchema.php',
		'COciCommandBuilder' => '/db/schema/oci/COciCommandBuilder.php',
		'COciSchema' => '/db/schema/oci/COciSchema.php',
		'COciTableSchema' => '/db/schema/oci/COciTableSchema.php',
		'CPgsqlColumnSchema' => '/db/schema/pgsql/CPgsqlColumnSchema.php',
		'CPgsqlSchema' => '/db/schema/pgsql/CPgsqlSchema.php',
		'CPgsqlTableSchema' => '/db/schema/pgsql/CPgsqlTableSchema.php',
		'CSqliteColumnSchema' => '/db/schema/sqlite/CSqliteColumnSchema.php',
		'CSqliteCommandBuilder' => '/db/schema/sqlite/CSqliteCommandBuilder.php',
		'CSqliteSchema' => '/db/schema/sqlite/CSqliteSchema.php',
		'CChoiceFormat' => '/i18n/CChoiceFormat.php',
		'CDateFormatter' => '/i18n/CDateFormatter.php',
		'CDbMessageSource' => '/i18n/CDbMessageSource.php',
		'CGettextMessageSource' => '/i18n/CGettextMessageSource.php',
		'CLocale' => '/i18n/CLocale.php',
		'CMessageSource' => '/i18n/CMessageSource.php',
		'CNumberFormatter' => '/i18n/CNumberFormatter.php',
		'CPhpMessageSource' => '/i18n/CPhpMessageSource.php',
		'CGettextFile' => '/i18n/gettext/CGettextFile.php',
		'CGettextMoFile' => '/i18n/gettext/CGettextMoFile.php',
		'CGettextPoFile' => '/i18n/gettext/CGettextPoFile.php',
		'CDbLogRoute' => '/logging/CDbLogRoute.php',
		'CEmailLogRoute' => '/logging/CEmailLogRoute.php',
		'CFileLogRoute' => '/logging/CFileLogRoute.php',
		'CLogFilter' => '/logging/CLogFilter.php',
		'CLogRoute' => '/logging/CLogRoute.php',
		'CLogRouter' => '/logging/CLogRouter.php',
		'CLogger' => '/logging/CLogger.php',
		'CProfileLogRoute' => '/logging/CProfileLogRoute.php',
		'CWebLogRoute' => '/logging/CWebLogRoute.php',
		'CDateTimeParser' => '/utils/CDateTimeParser.php',
		'CFileHelper' => '/utils/CFileHelper.php',
		'CMarkdownParser' => '/utils/CMarkdownParser.php',
		'CPropertyValue' => '/utils/CPropertyValue.php',
		'CTimestamp' => '/utils/CTimestamp.php',
		'CVarDumper' => '/utils/CVarDumper.php',
		'CBooleanValidator' => '/validators/CBooleanValidator.php',
		'CCaptchaValidator' => '/validators/CCaptchaValidator.php',
		'CCompareValidator' => '/validators/CCompareValidator.php',
		'CDefaultValueValidator' => '/validators/CDefaultValueValidator.php',
		'CEmailValidator' => '/validators/CEmailValidator.php',
		'CExistValidator' => '/validators/CExistValidator.php',
		'CFileValidator' => '/validators/CFileValidator.php',
		'CFilterValidator' => '/validators/CFilterValidator.php',
		'CInlineValidator' => '/validators/CInlineValidator.php',
		'CNumberValidator' => '/validators/CNumberValidator.php',
		'CRangeValidator' => '/validators/CRangeValidator.php',
		'CRegularExpressionValidator' => '/validators/CRegularExpressionValidator.php',
		'CRequiredValidator' => '/validators/CRequiredValidator.php',
		'CStringValidator' => '/validators/CStringValidator.php',
		'CTypeValidator' => '/validators/CTypeValidator.php',
		'CUniqueValidator' => '/validators/CUniqueValidator.php',
		'CUrlValidator' => '/validators/CUrlValidator.php',
		'CValidator' => '/validators/CValidator.php',
		'CAssetManager' => '/web/CAssetManager.php',
		'CBaseController' => '/web/CBaseController.php',
		'CCacheHttpSession' => '/web/CCacheHttpSession.php',
		'CClientScript' => '/web/CClientScript.php',
		'CController' => '/web/CController.php',
		'CDbHttpSession' => '/web/CDbHttpSession.php',
		'CExtController' => '/web/CExtController.php',
		'CFormModel' => '/web/CFormModel.php',
		'CHttpCookie' => '/web/CHttpCookie.php',
		'CHttpRequest' => '/web/CHttpRequest.php',
		'CHttpSession' => '/web/CHttpSession.php',
		'CHttpSessionIterator' => '/web/CHttpSessionIterator.php',
		'COutputEvent' => '/web/COutputEvent.php',
		'CPagination' => '/web/CPagination.php',
		'CSort' => '/web/CSort.php',
		'CTheme' => '/web/CTheme.php',
		'CThemeManager' => '/web/CThemeManager.php',
		'CUploadedFile' => '/web/CUploadedFile.php',
		'CUrlManager' => '/web/CUrlManager.php',
		'CWebApplication' => '/web/CWebApplication.php',
		'CWebModule' => '/web/CWebModule.php',
		'CAction' => '/web/actions/CAction.php',
		'CInlineAction' => '/web/actions/CInlineAction.php',
		'CViewAction' => '/web/actions/CViewAction.php',
		'CAccessControlFilter' => '/web/auth/CAccessControlFilter.php',
		'CAuthAssignment' => '/web/auth/CAuthAssignment.php',
		'CAuthItem' => '/web/auth/CAuthItem.php',
		'CAuthManager' => '/web/auth/CAuthManager.php',
		'CBaseUserIdentity' => '/web/auth/CBaseUserIdentity.php',
		'CDbAuthManager' => '/web/auth/CDbAuthManager.php',
		'CPhpAuthManager' => '/web/auth/CPhpAuthManager.php',
		'CUserIdentity' => '/web/auth/CUserIdentity.php',
		'CWebUser' => '/web/auth/CWebUser.php',
		'CFilter' => '/web/filters/CFilter.php',
		'CFilterChain' => '/web/filters/CFilterChain.php',
		'CInlineFilter' => '/web/filters/CInlineFilter.php',
		'CGoogleApi' => '/web/helpers/CGoogleApi.php',
		'CHtml' => '/web/helpers/CHtml.php',
		'CJSON' => '/web/helpers/CJSON.php',
		'CJavaScript' => '/web/helpers/CJavaScript.php',
		'CPradoViewRenderer' => '/web/renderers/CPradoViewRenderer.php',
		'CViewRenderer' => '/web/renderers/CViewRenderer.php',
		'CWebService' => '/web/services/CWebService.php',
		'CWebServiceAction' => '/web/services/CWebServiceAction.php',
		'CWsdlGenerator' => '/web/services/CWsdlGenerator.php',
		'CAutoComplete' => '/web/widgets/CAutoComplete.php',
		'CClipWidget' => '/web/widgets/CClipWidget.php',
		'CContentDecorator' => '/web/widgets/CContentDecorator.php',
		'CFilterWidget' => '/web/widgets/CFilterWidget.php',
		'CFlexWidget' => '/web/widgets/CFlexWidget.php',
		'CHtmlPurifier' => '/web/widgets/CHtmlPurifier.php',
		'CInputWidget' => '/web/widgets/CInputWidget.php',
		'CMarkdown' => '/web/widgets/CMarkdown.php',
		'CMaskedTextField' => '/web/widgets/CMaskedTextField.php',
		'CMultiFileUpload' => '/web/widgets/CMultiFileUpload.php',
		'COutputCache' => '/web/widgets/COutputCache.php',
		'COutputProcessor' => '/web/widgets/COutputProcessor.php',
		'CStarRating' => '/web/widgets/CStarRating.php',
		'CTabView' => '/web/widgets/CTabView.php',
		'CTextHighlighter' => '/web/widgets/CTextHighlighter.php',
		'CTreeView' => '/web/widgets/CTreeView.php',
		'CWidget' => '/web/widgets/CWidget.php',
		'CCaptcha' => '/web/widgets/captcha/CCaptcha.php',
		'CCaptchaAction' => '/web/widgets/captcha/CCaptchaAction.php',
		'CBasePager' => '/web/widgets/pagers/CBasePager.php',
		'CLinkPager' => '/web/widgets/pagers/CLinkPager.php',
		'CListPager' => '/web/widgets/pagers/CListPager.php',
	);
}
spl_autoload_register(array('YiiBase','autoload'));
class Yii extends YiiBase
{
}
class CComponent
{
	private $_e;
	private $_m;
	public function __get($name)
	{
		$getter='get'.$name;
		if(method_exists($this,$getter))
			return $this->$getter();
		else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
		{
			// duplicating getEventHandlers() here for performance
			$name=strtolower($name);
			if(!isset($this->_e[$name]))
				$this->_e[$name]=new CList;
			return $this->_e[$name];
		}
		else if(isset($this->_m[$name]))
			return $this->_m[$name];
		else
			throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
				array('{class}'=>get_class($this), '{property}'=>$name)));
	}
	public function __set($name,$value)
	{
		$setter='set'.$name;
		if(method_exists($this,$setter))
			$this->$setter($value);
		else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
		{
			// duplicating getEventHandlers() here for performance
			$name=strtolower($name);
			if(!isset($this->_e[$name]))
				$this->_e[$name]=new CList;
			$this->_e[$name]->add($value);
		}
		else if(method_exists($this,'get'.$name))
			throw new CException(Yii::t('yii','Property "{class}.{property}" is read only.',
				array('{class}'=>get_class($this), '{property}'=>$name)));
		else
			throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
				array('{class}'=>get_class($this), '{property}'=>$name)));
	}
	public function __isset($name)
	{
		$getter='get'.$name;
		if(method_exists($this,$getter))
			return $this->$getter()!==null;
		else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
		{
			$name=strtolower($name);
			return isset($this->_e[$name]) && $this->_e[$name]->getCount();
		}
		else
			return false;
	}
	public function __unset($name)
	{
		$setter='set'.$name;
		if(method_exists($this,$setter))
			$this->$setter(null);
		else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
			unset($this->_e[strtolower($name)]);
		else if(method_exists($this,'get'.$name))
			throw new CException(Yii::t('yii','Property "{class}.{property}" is read only.',
				array('{class}'=>get_class($this), '{property}'=>$name)));
	}
	public function __call($name,$parameters)
	{
		if($this->_m!==null)
		{
			foreach($this->_m as $object)
			{
				if($object->enabled && method_exists($object,$name))
					return call_user_func_array(array($object,$name),$parameters);
			}
		}
		throw new CException(Yii::t('yii','{class} does not have a method named "{name}".',
			array('{class}'=>get_class($this), '{name}'=>$name)));
	}
	public function asa($behavior)
	{
		return isset($this->_m[$behavior]) ? $this->_m[$behavior] : null;
	}
	public function attachBehaviors($behaviors)
	{
		foreach($behaviors as $name=>$behavior)
			$this->attachBehavior($name,$behavior);
	}
	public function detachBehaviors()
	{
		if($this->_m!==null)
		{
			foreach($this->_m as $name=>$behavior)
				$this->detachBehavior($name);
			$this->_m=null;
		}
	}
	public function attachBehavior($name,$behavior)
	{
		if(!($behavior instanceof IBehavior))
			$behavior=Yii::createComponent($behavior);
		$behavior->setEnabled(true);
		$behavior->attach($this);
		return $this->_m[$name]=$behavior;
	}
	public function detachBehavior($name)
	{
		if(isset($this->_m[$name]))
		{
			$this->_m[$name]->detach($this);
			$behavior=$this->_m[$name];
			unset($this->_m[$name]);
			return $behavior;
		}
	}
	public function enableBehaviors()
	{
		if($this->_m!==null)
		{
			foreach($this->_m as $behavior)
				$behavior->setEnabled(true);
		}
	}
	public function disableBehaviors()
	{
		if($this->_m!==null)
		{
			foreach($this->_m as $behavior)
				$behavior->setEnabled(false);
		}
	}
	public function enableBehavior($name)
	{
		if(isset($this->_m[$name]))
			$this->_m[$name]->setEnabled(true);
	}
	public function disableBehavior($name)
	{
		if(isset($this->_m[$name]))
			$this->_m[$name]->setEnabled(false);
	}
	public function hasProperty($name)
	{
		return method_exists($this,'get'.$name) || method_exists($this,'set'.$name);
	}
	public function canGetProperty($name)
	{
		return method_exists($this,'get'.$name);
	}
	public function canSetProperty($name)
	{
		return method_exists($this,'set'.$name);
	}
	public function hasEvent($name)
	{
		return !strncasecmp($name,'on',2) && method_exists($this,$name);
	}
	public function hasEventHandler($name)
	{
		$name=strtolower($name);
		return isset($this->_e[$name]) && $this->_e[$name]->getCount()>0;
	}
	public function getEventHandlers($name)
	{
		if($this->hasEvent($name))
		{
			$name=strtolower($name);
			if(!isset($this->_e[$name]))
				$this->_e[$name]=new CList;
			return $this->_e[$name];
		}
		else
			throw new CException(Yii::t('yii','Event "{class}.{event}" is not defined.',
				array('{class}'=>get_class($this), '{event}'=>$name)));
	}
	public function attachEventHandler($name,$handler)
	{
		$this->getEventHandlers($name)->add($handler);
	}
	public function detachEventHandler($name,$handler)
	{
		if($this->hasEventHandler($name))
			return $this->getEventHandlers($name)->remove($handler)!==false;
		else
			return false;
	}
	public function raiseEvent($name,$event)
	{
		$name=strtolower($name);
		if(isset($this->_e[$name]))
		{
			foreach($this->_e[$name] as $handler)
			{
				if(is_string($handler))
					call_user_func($handler,$event);
				else if(is_callable($handler,true))
				{
					if(is_array($handler))
					{
						// an array: 0 - object, 1 - method name
						list($object,$method)=$handler;
						if(is_string($object))	// static method call
							call_user_func($handler,$event);
						else if(method_exists($object,$method))
							$object->$method($event);
						else
							throw new CException(Yii::t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
								array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>$handler[1])));
					}
					else // PHP 5.3: anonymous function
						call_user_func($handler,$event);
				}
				else
					throw new CException(Yii::t('yii','Event "{class}.{event}" is attached with an invalid handler "{handler}".',
						array('{class}'=>get_class($this), '{event}'=>$name, '{handler}'=>gettype($handler))));
				// stop further handling if param.handled is set true
				if(($event instanceof CEvent) && $event->handled)
					return;
			}
		}
		else if(YII_DEBUG && !$this->hasEvent($name))
			throw new CException(Yii::t('yii','Event "{class}.{event}" is not defined.',
				array('{class}'=>get_class($this), '{event}'=>$name)));
	}
}
class CEvent extends CComponent
{
	public $sender;
	public $handled=false;
	public function __construct($sender=null)
	{
		$this->sender=$sender;
	}
}
class CEnumerable
{
}
abstract class CModule extends CComponent
{
	public $preload=array();
	public $behaviors=array();
	private $_id;
	private $_parentModule;
	private $_basePath;
	private $_modulePath;
	private $_params;
	private $_modules=array();
	private $_moduleConfig=array();
	private $_components=array();
	private $_componentConfig=array();
	public function __construct($id,$parent,$config=null)
	{
		$this->_id=$id;
		$this->_parentModule=$parent;
		// set basePath at early as possible to avoid trouble
		if(is_string($config))
			$config=require($config);
		if(isset($config['basePath']))
		{
			$this->setBasePath($config['basePath']);
			unset($config['basePath']);
		}
		else
		{
			$class=new ReflectionClass(get_class($this));
			$this->setBasePath(dirname($class->getFileName()));
		}
		Yii::setPathOfAlias($id,$this->getBasePath());
		$this->preinit();
		$this->configure($config);
		$this->attachBehaviors($this->behaviors);
		$this->preloadComponents();
		$this->init();
	}
	public function __get($name)
	{
		if($this->hasComponent($name))
			return $this->getComponent($name);
		else
			return parent::__get($name);
	}
	public function __isset($name)
	{
		if($this->hasComponent($name))
			return $this->getComponent($name)!==null;
		else
			return parent::__isset($name);
	}
	public function getId()
	{
		return $this->_id;
	}
	public function setId($id)
	{
		$this->_id=$id;
	}
	public function getBasePath()
	{
		if($this->_basePath===null)
		{
			$class=new ReflectionClass(get_class($this));
			$this->_basePath=dirname($class->getFileName());
		}
		return $this->_basePath;
	}
	public function setBasePath($path)
	{
		if(($this->_basePath=realpath($path))===false || !is_dir($this->_basePath))
			throw new CException(Yii::t('yii','Base path "{path}" is not a valid directory.',
				array('{path}'=>$path)));
	}
	public function getParams()
	{
		if($this->_params!==null)
			return $this->_params;
		else
			return $this->_params=new CAttributeCollection;
	}
	public function setParams($value)
	{
		$params=$this->getParams();
		foreach($value as $k=>$v)
			$params->add($k,$v);
	}
	public function getModulePath()
	{
		if($this->_modulePath!==null)
			return $this->_modulePath;
		else
			return $this->_modulePath=$this->getBasePath().DIRECTORY_SEPARATOR.'modules';
	}
	public function setModulePath($value)
	{
		if(($this->_modulePath=realpath($value))===false || !is_dir($this->_modulePath))
			throw new CException(Yii::t('yii','The module path "{path}" is not a valid directory.',
				array('{path}'=>$value)));
	}
	public function setImport($aliases)
	{
		foreach($aliases as $alias)
			Yii::import($alias);
	}
	public function setAliases($mappings)
	{
		foreach($mappings as $name=>$alias)
		{
			if(($path=Yii::getPathOfAlias($alias))!==false)
				Yii::setPathOfAlias($name,$path);
			else
				Yii::setPathOfAlias($name,$alias);
		}
	}
	public function getParentModule()
	{
		return $this->_parentModule;
	}
	public function getModule($id)
	{
		if(isset($this->_modules[$id]) || array_key_exists($id,$this->_modules))
			return $this->_modules[$id];
		else if(isset($this->_moduleConfig[$id]))
		{
			$config=$this->_moduleConfig[$id];
			if(!isset($config['enabled']) || $config['enabled'])
			{
				$class=$config['class'];
				unset($config['class'], $config['enabled']);
				if($this===Yii::app())
					$module=Yii::createComponent($class,$id,null,$config);
				else
					$module=Yii::createComponent($class,$this->getId().'/'.$id,$this,$config);
				return $this->_modules[$id]=$module;
			}
		}
	}
	public function getModules()
	{
		return $this->_moduleConfig;
	}
	public function setModules($modules)
	{
		foreach($modules as $id=>$module)
		{
			if(is_int($id))
			{
				$id=$module;
				$module=array();
			}
			if(!isset($module['class']))
			{
				Yii::setPathOfAlias($id,$this->getModulePath().DIRECTORY_SEPARATOR.$id);
				$module['class']=$id.'.'.ucfirst($id).'Module';
			}
			if(isset($this->_moduleConfig[$id]))
				$this->_moduleConfig[$id]=CMap::mergeArray($this->_moduleConfig[$id],$module);
			else
				$this->_moduleConfig[$id]=$module;
		}
	}
	public function hasComponent($id)
	{
		return isset($this->_components[$id]) || isset($this->_componentConfig[$id]);
	}
	public function getComponent($id,$createIfNull=true)
	{
		if(isset($this->_components[$id]))
			return $this->_components[$id];
		else if(isset($this->_componentConfig[$id]) && $createIfNull)
		{
			$config=$this->_componentConfig[$id];
			unset($this->_componentConfig[$id]);
			if(!isset($config['enabled']) || $config['enabled'])
			{
				unset($config['enabled']);
				$component=Yii::createComponent($config);
				$component->init();
				return $this->_components[$id]=$component;
			}
		}
	}
	public function setComponent($id,$component)
	{
		$this->_components[$id]=$component;
		if(!$component->getIsInitialized())
			$component->init();
	}
	public function getComponents()
	{
		return $this->_components;
	}
	public function setComponents($components)
	{
		foreach($components as $id=>$component)
		{
			if($component instanceof IApplicationComponent)
				$this->setComponent($id,$component);
			else if(isset($this->_componentConfig[$id]))
				$this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);
			else
				$this->_componentConfig[$id]=$component;
		}
	}
	public function configure($config)
	{
		if(is_array($config))
		{
			foreach($config as $key=>$value)
				$this->$key=$value;
		}
	}
	protected function preloadComponents()
	{
		foreach($this->preload as $id)
			$this->getComponent($id);
	}
	protected function preinit()
	{
	}
	protected function init()
	{
	}
}
abstract class CApplication extends CModule
{
	public $name='My Application';
	public $charset='UTF-8';
	public $sourceLanguage='en_us';
	private $_id;
	private $_basePath;
	private $_runtimePath;
	private $_extensionPath;
	private $_globalState;
	private $_stateChanged;
	private $_ended=false;
	private $_language;
	abstract public function processRequest();
	public function __construct($config=null)
	{
		Yii::setApplication($this);
		// set basePath at early as possible to avoid trouble
		if(is_string($config))
			$config=require($config);
		if(isset($config['basePath']))
		{
			$this->setBasePath($config['basePath']);
			unset($config['basePath']);
		}
		else
			$this->setBasePath('protected');
		Yii::setPathOfAlias('application',$this->getBasePath());
		Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME']));
		Yii::setPathOfAlias('ext',$this->getBasePath().DIRECTORY_SEPARATOR.'extensions');
		$this->preinit();
		$this->initSystemHandlers();
		$this->registerCoreComponents();
		$this->configure($config);
		$this->attachBehaviors($this->behaviors);
		$this->preloadComponents();
		$this->init();
	}
	public function run()
	{
		if($this->hasEventHandler('onBeginRequest'))
			$this->onBeginRequest(new CEvent($this));
		$this->processRequest();
		if($this->hasEventHandler('onEndRequest'))
			$this->onEndRequest(new CEvent($this));
	}
	public function end($status=0)
	{
		if($this->hasEventHandler('onEndRequest'))
			$this->onEndRequest(new CEvent($this));
		exit($status);
	}
	public function onBeginRequest($event)
	{
		$this->raiseEvent('onBeginRequest',$event);
	}
	public function onEndRequest($event)
	{
		if(!$this->_ended)
		{
			$this->_ended=true;
			$this->raiseEvent('onEndRequest',$event);
		}
	}
	public function getId()
	{
		if($this->_id!==null)
			return $this->_id;
		else
			return $this->_id=sprintf('%x',crc32($this->getBasePath().$this->name));
	}
	public function setId($id)
	{
		$this->_id=$id;
	}
	public function getBasePath()
	{
		return $this->_basePath;
	}
	public function setBasePath($path)
	{
		if(($this->_basePath=realpath($path))===false || !is_dir($this->_basePath))
			throw new CException(Yii::t('yii','Application base path "{path}" is not a valid directory.',
				array('{path}'=>$path)));
	}
	public function getRuntimePath()
	{
		if($this->_runtimePath!==null)
			return $this->_runtimePath;
		else
		{
			$this->setRuntimePath($this->getBasePath().DIRECTORY_SEPARATOR.'runtime');
			return $this->_runtimePath;
		}
	}
	public function setRuntimePath($path)
	{
		if(($runtimePath=realpath($path))===false || !is_dir($runtimePath) || !is_writable($runtimePath))
			throw new CException(Yii::t('yii','Application runtime path "{path}" is not valid. Please make sure it is a directory writable by the Web server process.',
				array('{path}'=>$path)));
		$this->_runtimePath=$runtimePath;
	}
	public function getExtensionPath()
	{
		return Yii::getPathOfAlias('ext');
	}
	public function setExtensionPath($path)
	{
		if(($extensionPath=realpath($path))===false || !is_dir($extensionPath))
			throw new CException(Yii::t('yii','Extension path "{path}" does not exist.',
				array('{path}'=>$path)));
		Yii::setPathOfAlias('ext',$extensionPath);
	}
	public function getLanguage()
	{
		return $this->_language===null ? $this->sourceLanguage : $this->_language;
	}
	public function setLanguage($language)
	{
		$this->_language=$language;
	}
	public function getTimeZone()
	{
		return date_default_timezone_get();
	}
	public function setTimeZone($value)
	{
		date_default_timezone_set($value);
	}
	public function findLocalizedFile($srcFile,$srcLanguage=null,$language=null)
	{
		if($srcLanguage===null)
			$srcLanguage=$this->sourceLanguage;
		if($language===null)
			$language=$this->getLanguage();
		if($language===$srcLanguage)
			return $srcFile;
		$desiredFile=dirname($srcFile).DIRECTORY_SEPARATOR.$language.DIRECTORY_SEPARATOR.basename($srcFile);
		return is_file($desiredFile) ? $desiredFile : $srcFile;
	}
	public function getLocale($localeID=null)
	{
		return CLocale::getInstance($localeID===null?$this->getLanguage():$localeID);
	}
	public function getNumberFormatter()
	{
		return $this->getLocale()->getNumberFormatter();
	}
	public function getDateFormatter()
	{
		return $this->getLocale()->getDateFormatter();
	}
	public function getDb()
	{
		return $this->getComponent('db');
	}
	public function getErrorHandler()
	{
		return $this->getComponent('errorHandler');
	}
	public function getSecurityManager()
	{
		return $this->getComponent('securityManager');
	}
	public function getStatePersister()
	{
		return $this->getComponent('statePersister');
	}
	public function getCache()
	{
		return $this->getComponent('cache');
	}
	public function getCoreMessages()
	{
		return $this->getComponent('coreMessages');
	}
	public function getMessages()
	{
		return $this->getComponent('messages');
	}
	public function getRequest()
	{
		return $this->getComponent('request');
	}
	public function getUrlManager()
	{
		return $this->getComponent('urlManager');
	}
	public function getGlobalState($key,$defaultValue=null)
	{
		if($this->_globalState===null)
			$this->loadGlobalState();
		if(isset($this->_globalState[$key]))
			return $this->_globalState[$key];
		else
			return $defaultValue;
	}
	public function setGlobalState($key,$value,$defaultValue=null)
	{
		if($this->_globalState===null)
			$this->loadGlobalState();
		$this->_stateChanged=true;
		if($value===$defaultValue)
			unset($this->_globalState[$key]);
		else
			$this->_globalState[$key]=$value;
	}
	public function clearGlobalState($key)
	{
		if($this->_globalState===null)
			$this->loadGlobalState();
		if(isset($this->_globalState[$key]))
		{
			$this->_stateChanged=true;
			unset($this->_globalState[$key]);
		}
	}
	protected function loadGlobalState()
	{
		$persister=$this->getStatePersister();
		if(($this->_globalState=$persister->load())===null)
			$this->_globalState=array();
		$this->_stateChanged=false;
		$this->attachEventHandler('onEndRequest',array($this,'saveGlobalState'));
	}
	protected function saveGlobalState()
	{
		if($this->_stateChanged)
		{
			$persister=$this->getStatePersister();
			$this->_stateChanged=false;
			$persister->save($this->_globalState);
		}
	}
	public function handleException($exception)
	{
		// disable error capturing to avoid recursive errors
		restore_error_handler();
		restore_exception_handler();
		$category='exception.'.get_class($exception);
		if($exception instanceof CHttpException)
			$category.='.'.$exception->statusCode;
		// php <5.2 doesn't support string conversion auto-magically
		$message=$exception->__toString();
		if(isset($_SERVER['REQUEST_URI']))
			$message.=' REQUEST_URI='.$_SERVER['REQUEST_URI'];
		Yii::log($message,CLogger::LEVEL_ERROR,$category);
		try
		{
			$event=new CExceptionEvent($this,$exception);
			$this->onException($event);
			if(!$event->handled)
			{
				// try an error handler
				if(($handler=$this->getErrorHandler())!==null)
					$handler->handle($event);
				else
					$this->displayException($exception);
			}
		}
		catch(Exception $e)
		{
			$this->displayException($e);
		}
		$this->end(1);
	}
	public function handleError($code,$message,$file,$line)
	{
		if($code & error_reporting())
		{
			// disable error capturing to avoid recursive errors
			restore_error_handler();
			restore_exception_handler();
			$log="$message ($file:$line)\nStack trace:\n";
			$trace=debug_backtrace();
			// skip the first 3 stacks as they do not tell the error position
			if(count($trace)>3)
				$trace=array_slice($trace,3);
			foreach($trace as $i=>$t)
			{
				if(!isset($t['file']))
					$t['file']='unknown';
				if(!isset($t['line']))
					$t['line']=0;
				if(!isset($t['function']))
					$t['function']='unknown';
				$log.="#$i {$t['file']}({$t['line']}): ";
				if(isset($t['object']) && is_object($t['object']))
					$log.=get_class($t['object']).'->';
				$log.="{$t['function']}()\n";
			}
			if(isset($_SERVER['REQUEST_URI']))
				$log.='REQUEST_URI='.$_SERVER['REQUEST_URI'];
			Yii::log($log,CLogger::LEVEL_ERROR,'php');
			try
			{
				$event=new CErrorEvent($this,$code,$message,$file,$line);
				$this->onError($event);
				if(!$event->handled)
				{
					// try an error handler
					if(($handler=$this->getErrorHandler())!==null)
						$handler->handle($event);
					else
						$this->displayError($code,$message,$file,$line);
				}
			}
			catch(Exception $e)
			{
				$this->displayException($e);
			}
			$this->end(1);
		}
	}
	public function onException($event)
	{
		$this->raiseEvent('onException',$event);
	}
	public function onError($event)
	{
		$this->raiseEvent('onError',$event);
	}
	public function displayError($code,$message,$file,$line)
	{
		if(YII_DEBUG)
		{
			echo "<h1>PHP Error [$code]</h1>\n";
			echo "<p>$message ($file:$line)</p>\n";
			echo '<pre>';
			debug_print_backtrace();
			echo '</pre>';
		}
		else
		{
			echo "<h1>PHP Error [$code]</h1>\n";
			echo "<p>$message</p>\n";
		}
	}
	public function displayException($exception)
	{
		if(YII_DEBUG)
		{
			echo '<h1>'.get_class($exception)."</h1>\n";
			echo '<p>'.$exception->getMessage().' ('.$exception->getFile().':'.$exception->getLine().')</p>';
			echo '<pre>'.$exception->getTraceAsString().'</pre>';
		}
		else
		{
			echo '<h1>'.get_class($exception)."</h1>\n";
			echo '<p>'.$exception->getMessage().'</p>';
		}
	}
	protected function initSystemHandlers()
	{
		if(YII_ENABLE_EXCEPTION_HANDLER)
			set_exception_handler(array($this,'handleException'));
		if(YII_ENABLE_ERROR_HANDLER)
			set_error_handler(array($this,'handleError'),error_reporting());
	}
	protected function registerCoreComponents()
	{
		$components=array(
			'coreMessages'=>array(
				'class'=>'CPhpMessageSource',
				'language'=>'en_us',
				'basePath'=>YII_PATH.DIRECTORY_SEPARATOR.'messages',
			),
			'db'=>array(
				'class'=>'CDbConnection',
			),
			'messages'=>array(
				'class'=>'CPhpMessageSource',
			),
			'errorHandler'=>array(
				'class'=>'CErrorHandler',
			),
			'securityManager'=>array(
				'class'=>'CSecurityManager',
			),
			'statePersister'=>array(
				'class'=>'CStatePersister',
			),
			'urlManager'=>array(
				'class'=>'CUrlManager',
			),
			'request'=>array(
				'class'=>'CHttpRequest',
			),
		);
		$this->setComponents($components);
	}
}
class CWebApplication extends CApplication
{
	public $defaultController='site';
	public $layout='main';
	public $controllerMap=array();
	public $catchAllRequest;
	private $_controllerPath;
	private $_viewPath;
	private $_systemViewPath;
	private $_layoutPath;
	private $_controller;
	private $_homeUrl;
	private $_theme;
	public function processRequest()
	{
		if(is_array($this->catchAllRequest) && isset($this->catchAllRequest[0]))
		{
			$route=$this->catchAllRequest[0];
			foreach(array_splice($this->catchAllRequest,1) as $name=>$value)
				$_GET[$name]=$value;
		}
		else
			$route=$this->getUrlManager()->parseUrl($this->getRequest());
		$this->runController($route);
	}
	protected function registerCoreComponents()
	{
		parent::registerCoreComponents();
		$components=array(
			'session'=>array(
				'class'=>'CHttpSession',
			),
			'assetManager'=>array(
				'class'=>'CAssetManager',
			),
			'user'=>array(
				'class'=>'CWebUser',
			),
			'themeManager'=>array(
				'class'=>'CThemeManager',
			),
			'authManager'=>array(
				'class'=>'CPhpAuthManager',
			),
			'clientScript'=>array(
				'class'=>'CClientScript',
			),
		);
		$this->setComponents($components);
	}
	public function getAuthManager()
	{
		return $this->getComponent('authManager');
	}
	public function getAssetManager()
	{
		return $this->getComponent('assetManager');
	}
	public function getSession()
	{
		return $this->getComponent('session');
	}
	public function getUser()
	{
		return $this->getComponent('user');
	}
	public function getViewRenderer()
	{
		return $this->getComponent('viewRenderer');
	}
	public function getClientScript()
	{
		return $this->getComponent('clientScript');
	}
	public function getThemeManager()
	{
		return $this->getComponent('themeManager');
	}
	public function getTheme()
	{
		if(is_string($this->_theme))
			$this->_theme=$this->getThemeManager()->getTheme($this->_theme);
		return $this->_theme;
	}
	public function setTheme($value)
	{
		$this->_theme=$value;
	}
	public function createUrl($route,$params=array(),$ampersand='&')
	{
		return $this->getUrlManager()->createUrl($route,$params,$ampersand);
	}
	public function createAbsoluteUrl($route,$params=array(),$schema='',$ampersand='&')
	{
		return $this->getRequest()->getHostInfo($schema).$this->createUrl($route,$params,$ampersand);
	}
	public function getBaseUrl($absolute=false)
	{
		return $this->getRequest()->getBaseUrl($absolute);
	}
	public function getHomeUrl()
	{
		if($this->_homeUrl===null)
		{
			if($this->getUrlManager()->showScriptName)
				return $this->getRequest()->getScriptUrl();
			else
				return $this->getRequest()->getBaseUrl().'/';
		}
		else
			return $this->_homeUrl;
	}
	public function setHomeUrl($value)
	{
		$this->_homeUrl=$value;
	}
	public function runController($route)
	{
		if(($ca=$this->createController($route))!==null)
		{
			list($controller,$actionID)=$ca;
			$oldController=$this->_controller;
			$this->_controller=$controller;
			$controller->init();
			$controller->run($actionID);
			$this->_controller=$oldController;
		}
		else
			throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
				array('{route}'=>$route===''?$this->defaultController:$route)));
	}
	public function createController($route,$owner=null)
	{
		if($owner===null)
			$owner=$this;
		if(($route=trim($route,'/'))==='')
			$route=$owner->defaultController;
		$caseSensitive=$this->getUrlManager()->caseSensitive;
		$route.='/';
		while(($pos=strpos($route,'/'))!==false)
		{
			$id=substr($route,0,$pos);
			if(!preg_match('/^\w+$/',$id))
				return null;
			if(!$caseSensitive)
				$id=strtolower($id);
			$route=(string)substr($route,$pos+1);
			if(!isset($basePath))  // first segment
			{
				if(isset($owner->controllerMap[$id]))
				{
					return array(
						Yii::createComponent($owner->controllerMap[$id],$id,$owner===$this?null:$owner),
						$this->parseActionParams($route),
					);
				}
				if(($module=$owner->getModule($id))!==null)
					return $this->createController($route,$module);
				$basePath=$owner->getControllerPath();
				$controllerID='';
			}
			else
				$controllerID.='/';
			$className=ucfirst($id).'Controller';
			$classFile=$basePath.DIRECTORY_SEPARATOR.$className.'.php';
			if(is_file($classFile))
			{
				if(!class_exists($className,false))
					require($classFile);
				if(class_exists($className,false) && is_subclass_of($className,'CController'))
				{
					$id[0]=strtolower($id[0]);
					return array(
						new $className($controllerID.$id,$owner===$this?null:$owner),
						$this->parseActionParams($route),
					);
				}
				return null;
			}
			$controllerID.=$id;
			$basePath.=DIRECTORY_SEPARATOR.$id;
		}
	}
	protected function parseActionParams($pathInfo)
	{
		if(($pos=strpos($pathInfo,'/'))!==false)
		{
			CUrlManager::parsePathInfo((string)substr($pathInfo,$pos+1));
			$actionID=substr($pathInfo,0,$pos);
			return $this->getUrlManager()->caseSensitive ? $actionID : strtolower($actionID);
		}
		else
			return $pathInfo;
	}
	public function getController()
	{
		return $this->_controller;
	}
	public function setController($value)
	{
		$this->_controller=$value;
	}
	public function getControllerPath()
	{
		if($this->_controllerPath!==null)
			return $this->_controllerPath;
		else
			return $this->_controllerPath=$this->getBasePath().DIRECTORY_SEPARATOR.'controllers';
	}
	public function setControllerPath($value)
	{
		if(($this->_controllerPath=realpath($value))===false || !is_dir($this->_controllerPath))
			throw new CException(Yii::t('yii','The controller path "{path}" is not a valid directory.',
				array('{path}'=>$value)));
	}
	public function getViewPath()
	{
		if($this->_viewPath!==null)
			return $this->_viewPath;
		else
			return $this->_viewPath=$this->getBasePath().DIRECTORY_SEPARATOR.'views';
	}
	public function setViewPath($path)
	{
		if(($this->_viewPath=realpath($path))===false || !is_dir($this->_viewPath))
			throw new CException(Yii::t('yii','The view path "{path}" is not a valid directory.',
				array('{path}'=>$path)));
	}
	public function getSystemViewPath()
	{
		if($this->_systemViewPath!==null)
			return $this->_systemViewPath;
		else
			return $this->_systemViewPath=$this->getViewPath().DIRECTORY_SEPARATOR.'system';
	}
	public function setSystemViewPath($path)
	{
		if(($this->_systemViewPath=realpath($path))===false || !is_dir($this->_systemViewPath))
			throw new CException(Yii::t('yii','The system view path "{path}" is not a valid directory.',
				array('{path}'=>$path)));
	}
	public function getLayoutPath()
	{
		if($this->_layoutPath!==null)
			return $this->_layoutPath;
		else
			return $this->_layoutPath=$this->getViewPath().DIRECTORY_SEPARATOR.'layouts';
	}
	public function setLayoutPath($path)
	{
		if(($this->_layoutPath=realpath($path))===false || !is_dir($this->_layoutPath))
			throw new CException(Yii::t('yii','The layout path "{path}" is not a valid directory.',
				array('{path}'=>$path)));
	}
	public function beforeControllerAction($controller,$action)
	{
		return true;
	}
	public function afterControllerAction($controller,$action)
	{
	}
	public function findModule($id)
	{
		if(($controller=$this->getController())!==null && ($module=$controller->getModule())!==null)
		{
			do
			{
				if(($m=$module->getModule($id))!==null)
					return $m;
			} while(($module=$module->getParentModule())!==null);
		}
		if(($m=$this->getModule($id))!==null)
			return $m;
	}
	protected function init()
	{
		parent::init();
		// preload 'request' so that it has chance to respond to onBeginRequest event.
		$this->getRequest();
	}
}
class CMap extends CComponent implements IteratorAggregate,ArrayAccess,Countable
{
	private $_d=array();
	private $_r=false;
	public function __construct($data=null,$readOnly=false)
	{
		if($data!==null)
			$this->copyFrom($data);
		$this->setReadOnly($readOnly);
	}
	public function getReadOnly()
	{
		return $this->_r;
	}
	protected function setReadOnly($value)
	{
		$this->_r=$value;
	}
	public function getIterator()
	{
		return new CMapIterator($this->_d);
	}
	public function count()
	{
		return $this->getCount();
	}
	public function getCount()
	{
		return count($this->_d);
	}
	public function getKeys()
	{
		return array_keys($this->_d);
	}
	public function itemAt($key)
	{
		if(isset($this->_d[$key]))
			return $this->_d[$key];
		else
			return null;
	}
	public function add($key,$value)
	{
		if(!$this->_r)
			$this->_d[$key]=$value;
		else
			throw new CException(Yii::t('yii','The map is read only.'));
	}
	public function remove($key)
	{
		if(!$this->_r)
		{
			if(isset($this->_d[$key]))
			{
				$value=$this->_d[$key];
				unset($this->_d[$key]);
				return $value;
			}
			else
			{
				// it is possible the value is null, which is not detected by isset
				unset($this->_d[$key]);
				return null;
			}
		}
		else
			throw new CException(Yii::t('yii','The map is read only.'));
	}
	public function clear()
	{
		foreach(array_keys($this->_d) as $key)
			$this->remove($key);
	}
	public function contains($key)
	{
		return isset($this->_d[$key]) || array_key_exists($key,$this->_d);
	}
	public function toArray()
	{
		return $this->_d;
	}
	public function copyFrom($data)
	{
		if(is_array($data) || $data instanceof Traversable)
		{
			if($this->getCount()>0)
				$this->clear();
			if($data instanceof CMap)
				$data=$data->_d;
			foreach($data as $key=>$value)
				$this->add($key,$value);
		}
		else if($data!==null)
			throw new CException(Yii::t('yii','Map data must be an array or an object implementing Traversable.'));
	}
	public function mergeWith($data,$recursive=true)
	{
		if(is_array($data) || $data instanceof Traversable)
		{
			if($data instanceof CMap)
				$data=$data->_d;
			if($recursive)
			{
				if($data instanceof Traversable)
				{
					$d=array();
					foreach($data as $key=>$value)
						$d[$key]=$value;
					$this->_d=self::mergeArray($this->_d,$d);
				}
				else
					$this->_d=self::mergeArray($this->_d,$data);
			}
			else
			{
				foreach($data as $key=>$value)
					$this->add($key,$value);
			}
		}
		else if($data!==null)
			throw new CException(Yii::t('yii','Map data must be an array or an object implementing Traversable.'));
	}
	public static function mergeArray($a,$b)
	{
		foreach($b as $k=>$v)
		{
			if(is_integer($k))
				$a[]=$v;
			else if(is_array($v) && isset($a[$k]) && is_array($a[$k]))
				$a[$k]=self::mergeArray($a[$k],$v);
			else
				$a[$k]=$v;
		}
		return $a;
	}
	public function offsetExists($offset)
	{
		return $this->contains($offset);
	}
	public function offsetGet($offset)
	{
		return $this->itemAt($offset);
	}
	public function offsetSet($offset,$item)
	{
		$this->add($offset,$item);
	}
	public function offsetUnset($offset)
	{
		$this->remove($offset);
	}
}
class CLogger extends CComponent
{
	const LEVEL_TRACE='trace';
	const LEVEL_WARNING='warning';
	const LEVEL_ERROR='error';
	const LEVEL_INFO='info';
	const LEVEL_PROFILE='profile';
	private $_logs=array();
	private $_levels;
	private $_categories;
	private $_timings;
	public function log($message,$level='info',$category='application')
	{
		$this->_logs[]=array($message,$level,$category,microtime(true));
	}
	public function getLogs($levels='',$categories='')
	{
		$this->_levels=preg_split('/[\s,]+/',strtolower($levels),-1,PREG_SPLIT_NO_EMPTY);
		$this->_categories=preg_split('/[\s,]+/',strtolower($categories),-1,PREG_SPLIT_NO_EMPTY);
		if(empty($levels) && empty($categories))
			return $this->_logs;
		else if(empty($levels))
			return array_values(array_filter(array_filter($this->_logs,array($this,'filterByCategory'))));
		else if(empty($categories))
			return array_values(array_filter(array_filter($this->_logs,array($this,'filterByLevel'))));
		else
		{
			$ret=array_values(array_filter(array_filter($this->_logs,array($this,'filterByLevel'))));
			return array_values(array_filter(array_filter($ret,array($this,'filterByCategory'))));
		}
	}
	private function filterByCategory($value)
	{
		foreach($this->_categories as $category)
		{
			$cat=strtolower($value[2]);
			if($cat===$category || (($c=rtrim($category,'.*'))!==$category && strpos($cat,$c)===0))
				return $value;
		}
		return false;
	}
	private function filterByLevel($value)
	{
		return in_array(strtolower($value[1]),$this->_levels)?$value:false;
	}
	public function getExecutionTime()
	{
		return microtime(true)-YII_BEGIN_TIME;
	}
	public function getMemoryUsage()
	{
		if(function_exists('memory_get_usage'))
			return memory_get_usage();
		else
		{
			$output=array();
			if(strncmp(PHP_OS,'WIN',3)===0)
			{
				exec('tasklist /FI "PID eq ' . getmypid() . '" /FO LIST',$output);
				return isset($output[5])?preg_replace('/[\D]/','',$output[5])*1024 : 0;
			}
			else
			{
				$pid=getmypid();
				exec("ps -eo%mem,rss,pid | grep $pid", $output);
				$output=explode("  ",$output[0]);
				return isset($output[1]) ? $output[1]*1024 : 0;
			}
		}
	}
	public function getProfilingResults($token=null,$category=null,$refresh=false)
	{
		if($this->_timings===null || $refresh)
			$this->calculateTimings();
		if($token===null && $category===null)
			return $this->_timings;
		$results=array();
		foreach($this->_timings as $timing)
		{
			if(($category===null || $timing[1]===$category) && ($token===null || $timing[0]===$token))
				$results[]=$timing[2];
		}
		return $results;
	}
	private function calculateTimings()
	{
		$this->_timings=array();
		$stack=array();
		foreach($this->_logs as $log)
		{
			if($log[1]!==CLogger::LEVEL_PROFILE)
				continue;
			list($message,$level,$category,$timestamp)=$log;
			if(!strncasecmp($message,'begin:',6))
			{
				$log[0]=substr($message,6);
				$stack[]=$log;
			}
			else if(!strncasecmp($message,'end:',4))
			{
				$token=substr($message,4);
				if(($last=array_pop($stack))!==null && $last[0]===$token)
				{
					$delta=$log[3]-$last[3];
					$this->_timings[]=array($message,$category,$delta);
				}
				else
					throw new CException(Yii::t('yii','CProfileLogRoute found a mismatching code block "{token}". Make sure the calls to Yii::beginProfile() and Yii::endProfile() be properly nested.',
						array('{token}'=>$token)));
			}
		}
		$now=microtime(true);
		while(($last=array_pop($stack))!==null)
		{
			$delta=$now-$last[3];
			$this->_timings[]=array($last[0],$last[2],$delta);
		}
	}
}
abstract class CApplicationComponent extends CComponent implements IApplicationComponent
{
	public $behaviors=array();
	private $_initialized=false;
	public function init()
	{
		$this->attachBehaviors($this->behaviors);
		$this->_initialized=true;
	}
	public function getIsInitialized()
	{
		return $this->_initialized;
	}
}
class CHttpRequest extends CApplicationComponent
{
	public $enableCookieValidation=false;
	public $enableCsrfValidation=false;
	public $csrfTokenName='YII_CSRF_TOKEN';
	public $csrfCookie;
	private $_requestUri;
	private $_pathInfo;
	private $_scriptFile;
	private $_scriptUrl;
	private $_hostInfo;
	private $_url;
	private $_baseUrl;
	private $_cookies;
	private $_preferredLanguage;
	private $_csrfToken;
	public function init()
	{
		parent::init();
		$this->normalizeRequest();
	}
	protected function normalizeRequest()
	{
		// normalize request
		if(get_magic_quotes_gpc())
		{
			if(isset($_GET))
				$_GET=$this->stripSlashes($_GET);
			if(isset($_POST))
				$_POST=$this->stripSlashes($_POST);
			if(isset($_REQUEST))
				$_REQUEST=$this->stripSlashes($_REQUEST);
			if(isset($_COOKIE))
				$_COOKIE=$this->stripSlashes($_COOKIE);
		}
		if($this->enableCsrfValidation)
			Yii::app()->attachEventHandler('onBeginRequest',array($this,'validateCsrfToken'));
	}
	public function stripSlashes(&$data)
	{
		return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data);
	}
	public function getParam($name,$defaultValue=null)
	{
		return isset($_GET[$name]) ? $_GET[$name] : (isset($_POST[$name]) ? $_POST[$name] : $defaultValue);
	}
	public function getQuery($name,$defaultValue=null)
	{
		return isset($_GET[$name]) ? $_GET[$name] : $defaultValue;
	}
	public function getPost($name,$defaultValue=null)
	{
		return isset($_POST[$name]) ? $_POST[$name] : $defaultValue;
	}
	public function getUrl()
	{
		if($this->_url!==null)
			return $this->_url;
		else
		{
			if(isset($_SERVER['REQUEST_URI']))
				$this->_url=$_SERVER['REQUEST_URI'];
			else
			{
				$this->_url=$this->getScriptUrl();
				if(($pathInfo=$this->getPathInfo())!=='')
					$this->_url.='/'.$pathInfo;
				if(($queryString=$this->getQueryString())!=='')
					$this->_url.='?'.$queryString;
			}
			return $this->_url;
		}
	}
	public function getHostInfo($schema='')
	{
		if($this->_hostInfo===null)
		{
			if($secure=$this->getIsSecureConnection())
				$http='https';
			else
				$http='http';
			if(isset($_SERVER['HTTP_HOST']))
				$this->_hostInfo=$http.'://'.$_SERVER['HTTP_HOST'];
			else
			{
				$this->_hostInfo=$http.'://'.$_SERVER['SERVER_NAME'];
				$port=$_SERVER['SERVER_PORT'];
				if(($port!=80 && !$secure) || ($port!=443 && $secure))
					$this->_hostInfo.=':'.$port;
			}
		}
		if($schema!=='' && ($pos=strpos($this->_hostInfo,':'))!==false)
			return $schema.substr($this->_hostInfo,$pos);
		else
			return $this->_hostInfo;
	}
	public function setHostInfo($value)
	{
		$this->_hostInfo=rtrim($value,'/');
	}
	public function getBaseUrl($absolute=false)
	{
		if($this->_baseUrl===null)
			$this->_baseUrl=rtrim(dirname($this->getScriptUrl()),'\\/');
		return $absolute ? $this->getHostInfo() . $this->_baseUrl : $this->_baseUrl;
	}
	public function setBaseUrl($value)
	{
		$this->_baseUrl=$value;
	}
	public function getScriptUrl()
	{
		if($this->_scriptUrl===null)
		{
			$scriptName=basename($_SERVER['SCRIPT_FILENAME']);
			if(basename($_SERVER['SCRIPT_NAME'])===$scriptName)
				$this->_scriptUrl=$_SERVER['SCRIPT_NAME'];
			else if(basename($_SERVER['PHP_SELF'])===$scriptName)
				$this->_scriptUrl=$_SERVER['PHP_SELF'];
			else if(isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME'])===$scriptName)
				$this->_scriptUrl=$_SERVER['ORIG_SCRIPT_NAME'];
			else if(($pos=strpos($_SERVER['PHP_SELF'],'/'.$scriptName))!==false)
				$this->_scriptUrl=substr($_SERVER['SCRIPT_NAME'],0,$pos).'/'.$scriptName;
			else if(isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'],$_SERVER['DOCUMENT_ROOT'])===0)
				$this->_scriptUrl=str_replace('\\','/',str_replace($_SERVER['DOCUMENT_ROOT'],'',$_SERVER['SCRIPT_FILENAME']));
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the entry script URL.'));
		}
		return $this->_scriptUrl;
	}
	public function setScriptUrl($value)
	{
		$this->_scriptUrl='/'.trim($value,'/');
	}
	public function getPathInfo()
	{
		if($this->_pathInfo===null)
		{
			$requestUri=$this->getRequestUri();
			$scriptUrl=$this->getScriptUrl();
			$baseUrl=$this->getBaseUrl();
			if(strpos($requestUri,$scriptUrl)===0)
				$pathInfo=substr($requestUri,strlen($scriptUrl));
			else if($baseUrl==='' || strpos($requestUri,$baseUrl)===0)
				$pathInfo=substr($requestUri,strlen($baseUrl));
			else if(strpos($_SERVER['PHP_SELF'],$scriptUrl)===0)
				$pathInfo=substr($_SERVER['PHP_SELF'],strlen($scriptUrl));
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the path info of the request.'));
			if(($pos=strpos($pathInfo,'?'))!==false)
				$pathInfo=substr($pathInfo,0,$pos);
			$this->_pathInfo=trim($pathInfo,'/');
		}
		return $this->_pathInfo;
	}
	public function getRequestUri()
	{
		if($this->_requestUri===null)
		{
			if(isset($_SERVER['HTTP_X_REWRITE_URL'])) // IIS
				$this->_requestUri=$_SERVER['HTTP_X_REWRITE_URL'];
			else if(isset($_SERVER['REQUEST_URI']))
			{
				$this->_requestUri=$_SERVER['REQUEST_URI'];
				if(strpos($this->_requestUri,$_SERVER['HTTP_HOST'])!==false)
					$this->_requestUri=preg_replace('/^\w+:\/\/[^\/]+/','',$this->_requestUri);
			}
			else if(isset($_SERVER['ORIG_PATH_INFO']))  // IIS 5.0 CGI
			{
				$this->_requestUri=$_SERVER['ORIG_PATH_INFO'];
				if(!empty($_SERVER['QUERY_STRING']))
					$this->_requestUri.='?'.$_SERVER['QUERY_STRING'];
			}
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the request URI.'));
		}
		return $this->_requestUri;
	}
	public function getQueryString()
	{
		return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:'';
	}
	public function getIsSecureConnection()
	{
	    return isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'],'on');
	}
	public function getRequestType()
	{
		return strtoupper(isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:'GET');
	}
	public function getIsPostRequest()
	{
		return !strcasecmp($_SERVER['REQUEST_METHOD'],'POST');
	}
	public function getIsAjaxRequest()
	{
		return isset($_SERVER['HTTP_X_REQUESTED_WITH'])?$_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest' : false;
	}
	public function getServerName()
	{
		return $_SERVER['SERVER_NAME'];
	}
	public function getServerPort()
	{
		return $_SERVER['SERVER_PORT'];
	}
	public function getUrlReferrer()
	{
		return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null;
	}
	public function getUserAgent()
	{
		return $_SERVER['HTTP_USER_AGENT'];
	}
	public function getUserHostAddress()
	{
		return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'127.0.0.1';
	}
	public function getUserHost()
	{
		return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null;
	}
	public function getScriptFile()
	{
		if($this->_scriptFile!==null)
			return $this->_scriptFile;
		else
			return $this->_scriptFile=realpath($_SERVER['SCRIPT_FILENAME']);
	}
	public function getBrowser($userAgent=null)
	{
		return get_browser($userAgent,true);
	}
	public function getAcceptTypes()
	{
		return $_SERVER['HTTP_ACCEPT'];
	}
	public function getCookies()
	{
		if($this->_cookies!==null)
			return $this->_cookies;
		else
			return $this->_cookies=new CCookieCollection($this);
	}
	public function redirect($url,$terminate=true,$statusCode=302)
	{
		if(strpos($url,'/')===0)
			$url=$this->getHostInfo().$url;
		header('Location: '.$url, true, $statusCode);
		if($terminate)
			Yii::app()->end();
	}
	public function getPreferredLanguage()
	{
		if($this->_preferredLanguage===null)
		{
			if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n=preg_match_all('/([\w\-_]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches))>0)
			{
				$languages=array();
				for($i=0;$i<$n;++$i)
					$languages[$matches[1][$i]]=empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]);
				arsort($languages);
				foreach($languages as $language=>$pref)
					return $this->_preferredLanguage=CLocale::getCanonicalID($language);
			}
			return $this->_preferredLanguage=false;
		}
		return $this->_preferredLanguage;
	}
	public function sendFile($fileName,$content,$mimeType=null,$terminate=true)
	{
		if($mimeType===null)
		{
			if(($mimeType=CFileHelper::getMimeTypeByExtension($fileName))===null)
				$mimeType='text/plain';
		}
		header('Pragma: public');
		header('Expires: 0');
		header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
		header("Content-type: $mimeType");
		header('Content-Length: '.strlen($content));
		header("Content-Disposition: attachment; filename=\"$fileName\"");
		header('Content-Transfer-Encoding: binary');
		echo $content;
		if($terminate)
			Yii::app()->end();
	}
	public function getCsrfToken()
	{
		if($this->_csrfToken===null)
		{
			$cookie=$this->getCookies()->itemAt($this->csrfTokenName);
			if(!$cookie || ($this->_csrfToken=$cookie->value)==null)
			{
				$cookie=$this->createCsrfCookie();
				$this->_csrfToken=$cookie->value;
				$this->getCookies()->add($cookie->name,$cookie);
			}
		}
		return $this->_csrfToken;
	}
	protected function createCsrfCookie()
	{
		$cookie=new CHttpCookie($this->csrfTokenName,sha1(uniqid(rand(),true)));
		if(is_array($this->csrfCookie))
		{
			foreach($this->csrfCookie as $name=>$value)
				$cookie->$name=$value;
		}
		return $cookie;
	}
	public function validateCsrfToken($event)
	{
		if($this->getIsPostRequest())
		{
			// only validate POST requests
			$cookies=$this->getCookies();
			if($cookies->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName]))
			{
				$tokenFromCookie=$cookies->itemAt($this->csrfTokenName)->value;
				$tokenFromPost=$_POST[$this->csrfTokenName];
				$valid=$tokenFromCookie===$tokenFromPost;
			}
			else
				$valid=false;
			if(!$valid)
				throw new CHttpException(400,Yii::t('yii','The CSRF token could not be verified.'));
		}
	}
}
class CCookieCollection extends CMap
{
	private $_request;
	private $_initialized=false;
	public function __construct(CHttpRequest $request)
	{
		$this->_request=$request;
		$this->copyfrom($this->getCookies());
		$this->_initialized=true;
	}
	public function getRequest()
	{
		return $this->_request;
	}
	protected function getCookies()
	{
		$cookies=array();
		if($this->_request->enableCookieValidation)
		{
			$sm=Yii::app()->getSecurityManager();
			foreach($_COOKIE as $name=>$value)
			{
				if(($value=$sm->validateData($value))!==false)
					$cookies[$name]=new CHttpCookie($name,$value);
			}
		}
		else
		{
			foreach($_COOKIE as $name=>$value)
				$cookies[$name]=new CHttpCookie($name,$value);
		}
		return $cookies;
	}
	public function add($name,$cookie)
	{
		if($cookie instanceof CHttpCookie)
		{
			$this->remove($name);
			parent::add($name,$cookie);
			if($this->_initialized)
				$this->addCookie($cookie);
		}
		else
			throw new CException(Yii::t('yii','CHttpCookieCollection can only hold CHttpCookie objects.'));
	}
	public function remove($name)
	{
		if(($cookie=parent::remove($name))!==null)
		{
			if($this->_initialized)
				$this->removeCookie($cookie);
		}
		return $cookie;
	}
	protected function addCookie($cookie)
	{
		$value=$cookie->value;
		if($this->_request->enableCookieValidation)
			$value=Yii::app()->getSecurityManager()->hashData($value);
		if(version_compare(PHP_VERSION,'5.2.0','>='))
			setcookie($cookie->name,$value,$cookie->expire,$cookie->path,$cookie->domain,$cookie->secure,$cookie->httpOnly);
		else
			setcookie($cookie->name,$value,$cookie->expire,$cookie->path,$cookie->domain,$cookie->secure);
	}
	protected function removeCookie($cookie)
	{
		if(version_compare(PHP_VERSION,'5.2.0','>='))
			setcookie($cookie->name,null,0,$cookie->path,$cookie->domain,$cookie->secure,$cookie->httpOnly);
		else
			setcookie($cookie->name,null,0,$cookie->path,$cookie->domain,$cookie->secure);
	}
}
class CUrlManager extends CApplicationComponent
{
	const CACHE_KEY='Yii.CUrlManager.rules';
	const GET_FORMAT='get';
	const PATH_FORMAT='path';
	public $rules=array();
	public $urlSuffix='';
	public $showScriptName=true;
	public $appendParams=true;
	public $routeVar='r';
	public $caseSensitive=true;
	public $cacheID='cache';
	public $useStrictParsing=false;
	private $_urlFormat=self::GET_FORMAT;
	private $_rules=array();
	private $_baseUrl;
	public function init()
	{
		parent::init();
		$this->processRules();
	}
	protected function processRules()
	{
		if(empty($this->rules) || $this->getUrlFormat()===self::GET_FORMAT)
			return;
		if($this->cacheID!==false && ($cache=Yii::app()->getComponent($this->cacheID))!==null)
		{
			$hash=md5(serialize($this->rules));
			if(($data=$cache->get(self::CACHE_KEY))!==false && isset($data[1]) && $data[1]===$hash)
			{
				$this->_rules=$data[0];
				return;
			}
		}
		foreach($this->rules as $pattern=>$route)
			$this->_rules[]=new CUrlRule($route,$pattern);
		if(isset($cache))
			$cache->set(self::CACHE_KEY,array($this->_rules,$hash));
	}
	public function createUrl($route,$params=array(),$ampersand='&')
	{
		unset($params[$this->routeVar]);
		foreach($params as &$param)
			if($param===null)
				$param='';
		if(isset($params['#']))
		{
			$anchor='#'.$params['#'];
			unset($params['#']);
		}
		else
			$anchor='';
		$route=trim($route,'/');
		foreach($this->_rules as $rule)
		{
			if(($url=$rule->createUrl($this,$route,$params,$ampersand))!==false)
				return $rule->hasHostInfo ? $url.$anchor : $this->getBaseUrl().'/'.$url.$anchor;
		}
		return $this->createUrlDefault($route,$params,$ampersand).$anchor;
	}
	protected function createUrlDefault($route,$params,$ampersand)
	{
		if($this->getUrlFormat()===self::PATH_FORMAT)
		{
			$url=rtrim($this->getBaseUrl().'/'.$route,'/');
			if($this->appendParams)
			{
				$url=rtrim($url.'/'.$this->createPathInfo($params,'/','/'),'/');
				return $route==='' ? $url : $url.$this->urlSuffix;
			}
			else
			{
				if($route!=='')
					$url.=$this->urlSuffix;
				$query=$this->createPathInfo($params,'=',$ampersand);
				return $query==='' ? $url : $url.'?'.$query;
			}
		}
		else
		{
			$url=$this->getBaseUrl();
			if(!$this->showScriptName)
				$url.='/';
			if($route!=='')
			{
				$url.='?'.$this->routeVar.'='.$route;
				if(($query=$this->createPathInfo($params,'=',$ampersand))!=='')
					$url.=$ampersand.$query;
			}
			else if(($query=$this->createPathInfo($params,'=',$ampersand))!=='')
				$url.='?'.$query;
			return $url;
		}
	}
	public function parseUrl($request)
	{
		if($this->getUrlFormat()===self::PATH_FORMAT)
		{
			$rawPathInfo=urldecode($request->getPathInfo());
			$pathInfo=$this->removeUrlSuffix($rawPathInfo,$this->urlSuffix);
			foreach($this->_rules as $rule)
			{
				if(($r=$rule->parseUrl($this,$request,$pathInfo,$rawPathInfo))!==false)
					return isset($_GET[$this->routeVar]) ? $_GET[$this->routeVar] : $r;
			}
			if($this->useStrictParsing)
				throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
					array('{route}'=>$pathInfo)));
			else
				return $pathInfo;
		}
		else if(isset($_GET[$this->routeVar]))
			return $_GET[$this->routeVar];
		else if(isset($_POST[$this->routeVar]))
			return $_POST[$this->routeVar];
		else
			return '';
	}
	public static function parsePathInfo($pathInfo)
	{
		if($pathInfo==='')
			return;
		$segs=explode('/',$pathInfo.'/');
		$n=count($segs);
		for($i=0;$i<$n-1;$i+=2)
		{
			$key=$segs[$i];
			if($key==='') continue;
			$value=$segs[$i+1];
			if(($pos=strpos($key,'['))!==false && ($pos2=strpos($key,']',$pos+1))!==false)
			{
				$name=substr($key,0,$pos);
				if($pos2===$pos+1)
					$_REQUEST[$name][]=$_GET[$name][]=$value;
				else
				{
					$key=substr($key,$pos+1,$pos2-$pos-1);
					$_REQUEST[$name][$key]=$_GET[$name][$key]=$value;
				}
			}
			else
				$_REQUEST[$key]=$_GET[$key]=$value;
		}
	}
	public function createPathInfo($params,$equal,$ampersand)
	{
		$pairs=array();
		foreach($params as $key=>$value)
		{
			if(is_array($value))
			{
				foreach($value as $k=>$v)
					$pairs[]=urlencode($key).'['.urlencode($k).']'.$equal.urlencode($v);
			}
			else
				$pairs[]=urlencode($key).$equal.urlencode($value);
		}
		return implode($ampersand,$pairs);
	}
	public function removeUrlSuffix($pathInfo,$urlSuffix)
	{
		if($urlSuffix!=='' && substr($pathInfo,-strlen($urlSuffix))===$urlSuffix)
			return substr($pathInfo,0,-strlen($urlSuffix));
		else
			return $pathInfo;
	}
	public function getBaseUrl()
	{
		if($this->_baseUrl!==null)
			return $this->_baseUrl;
		else
		{
			if($this->showScriptName)
				$this->_baseUrl=Yii::app()->getRequest()->getScriptUrl();
			else
				$this->_baseUrl=Yii::app()->getRequest()->getBaseUrl();
			return $this->_baseUrl;
		}
	}
	public function getUrlFormat()
	{
		return $this->_urlFormat;
	}
	public function setUrlFormat($value)
	{
		if($value===self::PATH_FORMAT || $value===self::GET_FORMAT)
			$this->_urlFormat=$value;
		else
			throw new CException(Yii::t('yii','CUrlManager.UrlFormat must be either "path" or "get".'));
	}
}
class CUrlRule extends CComponent
{
	public $urlSuffix;
	public $caseSensitive;
	public $defaultParams=array();
	public $route;
	public $references=array();
	public $routePattern;
	public $pattern;
	public $template;
	public $params=array();
	public $append;
	public $hasHostInfo;
	public function __construct($route,$pattern)
	{
		if(is_array($route))
		{
			if(isset($route['urlSuffix']))
				$this->urlSuffix=$route['urlSuffix'];
			if(isset($route['caseSensitive']))
				$this->caseSensitive=$route['caseSensitive'];
			if(isset($route['defaultParams']))
				$this->defaultParams=$route['defaultParams'];
			$route=$this->route=$route[0];
		}
		else
			$this->route=$route;
		$tr2['/']=$tr['/']='\\/';
		if(strpos($route,'<')!==false && preg_match_all('/<(\w+)>/',$route,$matches2))
		{
			foreach($matches2[1] as $name)
				$this->references[$name]="<$name>";
		}
		$this->hasHostInfo=!strncasecmp($pattern,'http://',7) || !strncasecmp($pattern,'https://',8);
		if(preg_match_all('/<(\w+):?(.*?)?>/',$pattern,$matches))
		{
			$tokens=array_combine($matches[1],$matches[2]);
			foreach($tokens as $name=>$value)
			{
				$tr["<$name>"]="(?P<$name>".($value!==''?$value:'[^\/]+').')';
				if(isset($this->references[$name]))
					$tr2["<$name>"]=$tr["<$name>"];
				else
					$this->params[$name]=$value;
			}
		}
		$p=rtrim($pattern,'*');
		$this->append=$p!==$pattern;
		$p=trim($p,'/');
		$this->template=preg_replace('/<(\w+):?.*?>/','<$1>',$p);
		$this->pattern='/^'.strtr($this->template,$tr).'\/';
		if($this->append)
			$this->pattern.='/u';
		else
			$this->pattern.='$/u';
		if($this->references!==array())
			$this->routePattern='/^'.strtr($this->route,$tr2).'$/u';
		if(YII_DEBUG && @preg_match($this->pattern,'test')===false)
			throw new CException(Yii::t('yii','The URL pattern "{pattern}" for route "{route}" is not a valid regular expression.',
				array('{route}'=>$route,'{pattern}'=>$pattern)));
	}
	public function createUrl($manager,$route,$params,$ampersand)
	{
		if($manager->caseSensitive && $this->caseSensitive===null || $this->caseSensitive)
			$case='';
		else
			$case='i';
		$tr=array();
		if($route!==$this->route)
		{
			if($this->routePattern!==null && preg_match($this->routePattern.$case,$route,$matches))
			{
				foreach($this->references as $key=>$name)
					$tr[$name]=$matches[$key];
			}
			else
				return false;
		}
		foreach($this->params as $key=>$value)
			if(!isset($params[$key]))
				return false;
		foreach($this->params as $key=>$value)
		{
			$tr["<$key>"]=urlencode($params[$key]);
			unset($params[$key]);
		}
		$suffix=$this->urlSuffix===null ? $manager->urlSuffix : $this->urlSuffix;
		$url=strtr($this->template,$tr);
		if(empty($params))
			return $url!=='' ? $url.$suffix : $url;
		if($this->append)
			$url.='/'.$manager->createPathInfo($params,'/','/').$suffix;
		else
		{
			if($url!=='')
				$url.=$suffix;
			$url.='?'.$manager->createPathInfo($params,'=',$ampersand);
		}
		return $url;
	}
	public function parseUrl($manager,$request,$pathInfo,$rawPathInfo)
	{
		if($manager->caseSensitive && $this->caseSensitive===null || $this->caseSensitive)
			$case='';
		else
			$case='i';
		if($this->urlSuffix!==null)
			$pathInfo=$manager->removeUrlSuffix($rawPathInfo,$this->urlSuffix);
		// URL suffix required, but not found in the requested URL
		if($manager->useStrictParsing && $pathInfo===$rawPathInfo)
		{
			$urlSuffix=$this->urlSuffix===null ? $manager->urlSuffix : $this->urlSuffix;
			if($urlSuffix!='' && $urlSuffix!=='/')
				throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
					array('{route}'=>$rawPathInfo)));
		}
		if($this->hasHostInfo)
			$pathInfo=$request->getHostInfo().rtrim('/'.$pathInfo,'/');
		$pathInfo.='/';
		if(preg_match($this->pattern.$case,$pathInfo,$matches))
		{
			foreach($this->defaultParams as $name=>$value)
			{
				if(!isset($_GET[$name]))
					$_REQUEST[$name]=$_GET[$name]=$value;
			}
			$tr=array();
			foreach($matches as $key=>$value)
			{
				if(isset($this->references[$key]))
					$tr[$this->references[$key]]=$value;
				else if(isset($this->params[$key]))
					$_REQUEST[$key]=$_GET[$key]=$value;
			}
			if($pathInfo!==$matches[0]) // there're additional GET params
				CUrlManager::parsePathInfo(ltrim(substr($pathInfo,strlen($matches[0])),'/'));
			if($this->routePattern!==null)
				return strtr($this->route,$tr);
			else
				return $this->route;
		}
		else
			return false;
	}
}
abstract class CBaseController extends CComponent
{
	private $_widgetStack=array();
	abstract public function getViewFile($viewName);
	public function renderFile($viewFile,$data=null,$return=false)
	{
		$widgetCount=count($this->_widgetStack);
		if(($renderer=Yii::app()->getViewRenderer())!==null)
			$content=$renderer->renderFile($this,$viewFile,$data,$return);
		else
			$content=$this->renderInternal($viewFile,$data,$return);
		if(count($this->_widgetStack)===$widgetCount)
			return $content;
		else
		{
			$widget=end($this->_widgetStack);
			throw new CException(Yii::t('yii','{controller} contains improperly nested widget tags in its view "{view}". A {widget} widget does not have an endWidget() call.',
				array('{controller}'=>get_class($this), '{view}'=>$viewFile, '{widget}'=>get_class($widget))));
		}
	}
	public function renderInternal($_viewFile_,$_data_=null,$_return_=false)
	{
		// we use special variable names here to avoid conflict when extracting data
		if(is_array($_data_))
			extract($_data_,EXTR_PREFIX_SAME,'data');
		else
			$data=$_data_;
		if($_return_)
		{
			ob_start();
			ob_implicit_flush(false);
			require($_viewFile_);
			return ob_get_clean();
		}
		else
			require($_viewFile_);
	}
	public function createWidget($className,$properties=array())
	{
		$className=Yii::import($className,true);
		$widget=new $className($this);
		foreach($properties as $name=>$value)
			$widget->$name=$value;
		$widget->init();
		return $widget;
	}
	public function widget($className,$properties=array())
	{
		$widget=$this->createWidget($className,$properties);
		$widget->run();
		return $widget;
	}
	public function beginWidget($className,$properties=array())
	{
		$widget=$this->createWidget($className,$properties);
		$this->_widgetStack[]=$widget;
		return $widget;
	}
	public function endWidget($id='')
	{
		if(($widget=array_pop($this->_widgetStack))!==null)
		{
			$widget->run();
			return $widget;
		}
		else
			throw new CException(Yii::t('yii','{controller} has an extra endWidget({id}) call in its view.',
				array('{controller}'=>get_class($this),'{id}'=>$id)));
	}
	public function beginClip($id,$properties=array())
	{
		$properties['id']=$id;
		$this->beginWidget('CClipWidget',$properties);
	}
	public function endClip()
	{
		$this->endWidget('CClipWidget');
	}
	public function beginCache($id,$properties=array())
	{
		$properties['id']=$id;
		$cache=$this->beginWidget('COutputCache',$properties);
		if($cache->getIsContentCached())
		{
			$this->endCache();
			return false;
		}
		else
			return true;
	}
	public function endCache()
	{
		$this->endWidget('COutputCache');
	}
	public function beginContent($view=null,$data=array())
	{
		$this->beginWidget('CContentDecorator',array('view'=>$view, 'data'=>$data));
	}
	public function endContent()
	{
		$this->endWidget('CContentDecorator');
	}
}
class CController extends CBaseController
{
	const STATE_INPUT_NAME='YII_PAGE_STATE';
	public $layout;
	public $defaultAction='index';
	private $_id;
	private $_action;
	private $_pageTitle;
	private $_cachingStack;
	private $_clips;
	private $_dynamicOutput;
	private $_pageStates;
	private $_module;
	public function __construct($id,$module=null)
	{
		$this->_id=$id;
		$this->_module=$module;
		$this->attachBehaviors($this->behaviors());
	}
	public function init()
	{
	}
	public function filters()
	{
		return array();
	}
	public function actions()
	{
		return array();
	}
	public function behaviors()
	{
		return array();
	}
	public function accessRules()
	{
		return array();
	}
	public function run($actionID)
	{
		if(($action=$this->createAction($actionID))!==null)
		{
			if(($parent=$this->getModule())===null)
				$parent=Yii::app();
			if($parent->beforeControllerAction($this,$action))
			{
				$this->runActionWithFilters($action,$this->filters());
				$parent->afterControllerAction($this,$action);
			}
		}
		else
			$this->missingAction($actionID);
	}
	public function runActionWithFilters($action,$filters)
	{
		if(empty($filters))
			$this->runAction($action);
		else
		{
			$priorAction=$this->_action;
			$this->_action=$action;
			CFilterChain::create($this,$action,$filters)->run();
			$this->_action=$priorAction;
		}
	}
	public function runAction($action)
	{
		$priorAction=$this->_action;
		$this->_action=$action;
		if($this->beforeAction($action))
		{
			$action->run();
			$this->afterAction($action);
		}
		$this->_action=$priorAction;
	}
	public function processOutput($output)
	{
		Yii::app()->getClientScript()->render($output);
		// if using page caching, we should delay dynamic output replacement
		if($this->_dynamicOutput!==null && $this->isCachingStackEmpty())
			$output=$this->processDynamicOutput($output);
		if($this->_pageStates===null)
			$this->_pageStates=$this->loadPageStates();
		if(!empty($this->_pageStates))
			$this->savePageStates($this->_pageStates,$output);
		return $output;
	}
	public function processDynamicOutput($output)
	{
		if($this->_dynamicOutput)
		{
			$output=preg_replace_callback('/<###dynamic-(\d+)###>/',array($this,'replaceDynamicOutput'),$output);
			$this->_dynamicOutput=null;
		}
		return $output;
	}
	protected function replaceDynamicOutput($matches)
	{
		return isset($this->_dynamicOutput[$matches[1]]) ? $this->_dynamicOutput[$matches[1]] : $matches[0];
	}
	public function createAction($actionID)
	{
		if($actionID==='')
			$actionID=$this->defaultAction;
		if(method_exists($this,'action'.$actionID) && strcasecmp($actionID,'s')) // we have actions method
			return new CInlineAction($this,$actionID);
		else
			return $this->createActionFromMap($this->actions(),$actionID,$actionID);
	}
	protected function createActionFromMap($actionMap,$actionID,$requestActionID,$config=array())
	{
		if(($pos=strpos($actionID,'.'))===false && isset($actionMap[$actionID]))
		{
			$baseConfig=is_array($actionMap[$actionID]) ? $actionMap[$actionID] : array('class'=>$actionMap[$actionID]);
			return Yii::createComponent(empty($config)?$baseConfig:array_merge($baseConfig,$config),$this,$requestActionID);
		}
		else if($pos===false)
			return null;
		// the action is defined in a provider
		$prefix=substr($actionID,0,$pos+1);
		if(!isset($actionMap[$prefix]))
			return null;
		$actionID=(string)substr($actionID,$pos+1);
		$provider=$actionMap[$prefix];
		if(is_string($provider))
			$providerType=$provider;
		else if(is_array($provider) && isset($provider['class']))
		{
			$providerType=$provider['class'];
			if(isset($provider[$actionID]))
			{
				if(is_string($provider[$actionID]))
					$config=array_merge(array('class'=>$provider[$actionID]),$config);
				else
					$config=array_merge($provider[$actionID],$config);
			}
		}
		else
			throw new CException(Yii::t('yii','Object configuration must be an array containing a "class" element.'));
		$class=Yii::import($providerType,true);
		$map=call_user_func(array($class,'actions'));
		return $this->createActionFromMap($map,$actionID,$requestActionID,$config);
	}
	public function missingAction($actionID)
	{
		throw new CHttpException(404,Yii::t('yii','The system is unable to find the requested action "{action}".',
			array('{action}'=>$actionID==''?$this->defaultAction:$actionID)));
	}
	public function getAction()
	{
		return $this->_action;
	}
	public function setAction($value)
	{
		$this->_action=$value;
	}
	public function getId()
	{
		return $this->_id;
	}
	public function getUniqueId()
	{
		return $this->_module ? $this->_module->getId().'/'.$this->_id : $this->_id;
	}
	public function getModule()
	{
		return $this->_module;
	}
	public function getViewPath()
	{
		if(($module=$this->getModule())===null)
			$module=Yii::app();
		return $module->getViewPath().'/'.$this->getId();
	}
	public function getViewFile($viewName)
	{
		if(($theme=Yii::app()->getTheme())!==null && ($viewFile=$theme->getViewFile($this,$viewName))!==false)
			return $viewFile;
		$module=$this->getModule();
		$basePath=$module ? $module->getViewPath() : Yii::app()->getViewPath();
		return $this->resolveViewFile($viewName,$this->getViewPath(),$basePath);
	}
	public function getLayoutFile($layoutName)
	{
		if($layoutName===false)
			return false;
		if(($theme=Yii::app()->getTheme())!==null && ($layoutFile=$theme->getLayoutFile($this,$layoutName))!==false)
			return $layoutFile;
		if(empty($layoutName))
		{
			$module=$this->getModule();
			while($module!==null)
			{
				if($module->layout===false)
					return false;
				if(!empty($module->layout))
					break;
				$module=$module->getParentModule();
			}
			if($module===null)
				$module=Yii::app();
			return $this->resolveViewFile($module->layout,$module->getLayoutPath(),$module->getViewPath());
		}
		else
		{
			if(($module=$this->getModule())===null)
				$module=Yii::app();
			return $this->resolveViewFile($layoutName,$module->getLayoutPath(),$module->getViewPath());
		}
	}
	public function resolveViewFile($viewName,$viewPath,$basePath)
	{
		if(empty($viewName))
			return false;
		if(($renderer=Yii::app()->getViewRenderer())!==null)
			$extension=$renderer->fileExtension;
		else
			$extension='.php';
		if($viewName[0]==='/')
			$viewFile=$basePath.$viewName.$extension;
		else if(strpos($viewName,'.'))
			$viewFile=Yii::getPathOfAlias($viewName).$extension;
		else
			$viewFile=$viewPath.DIRECTORY_SEPARATOR.$viewName.$extension;
		return is_file($viewFile) ? Yii::app()->findLocalizedFile($viewFile) : false;
	}
	public function getClips()
	{
		if($this->_clips!==null)
			return $this->_clips;
		else
			return $this->_clips=new CMap;
	}
	public function render($view,$data=null,$return=false)
	{
		$output=$this->renderPartial($view,$data,true);
		if(($layoutFile=$this->getLayoutFile($this->layout))!==false)
			$output=$this->renderFile($layoutFile,array('content'=>$output),true);
		$output=$this->processOutput($output);
		if($return)
			return $output;
		else
			echo $output;
	}
	public function renderText($text,$return=false)
	{
		if(($layoutFile=$this->getLayoutFile($this->layout))!==false)
			$text=$this->renderFile($layoutFile,array('content'=>$text),true);
		$text=$this->processOutput($text);
		if($return)
			return $text;
		else
			echo $text;
	}
	public function renderPartial($view,$data=null,$return=false,$processOutput=false)
	{
		if(($viewFile=$this->getViewFile($view))!==false)
		{
			$output=$this->renderFile($viewFile,$data,true);
			if($processOutput)
				$output=$this->processOutput($output);
			if($return)
				return $output;
			else
				echo $output;
		}
		else
			throw new CException(Yii::t('yii','{controller} cannot find the requested view "{view}".',
				array('{controller}'=>get_class($this), '{view}'=>$view)));
	}
	public function renderDynamic($callback)
	{
		$n=count($this->_dynamicOutput);
		echo "<###dynamic-$n###>";
		$params=func_get_args();
		array_shift($params);
		$this->renderDynamicInternal($callback,$params);
	}
	public function renderDynamicInternal($callback,$params)
	{
		$this->recordCachingAction('','renderDynamicInternal',array($callback,$params));
		if(is_string($callback) && method_exists($this,$callback))
			$callback=array($this,$callback);
		$this->_dynamicOutput[]=call_user_func_array($callback,$params);
	}
	public function createUrl($route,$params=array(),$ampersand='&')
	{
		if($route==='')
			$route=$this->getId().'/'.$this->getAction()->getId();
		else if(strpos($route,'/')===false)
			$route=$this->getId().'/'.$route;
		if($route[0]!=='/' && ($module=$this->getModule())!==null)
			$route=$module->getId().'/'.$route;
		return Yii::app()->createUrl(trim($route,'/'),$params,$ampersand);
	}
	public function createAbsoluteUrl($route,$params=array(),$schema='',$ampersand='&')
	{
		return Yii::app()->getRequest()->getHostInfo($schema).$this->createUrl($route,$params,$ampersand);
	}
	public function getPageTitle()
	{
		if($this->_pageTitle!==null)
			return $this->_pageTitle;
		else
		{
			$name=ucfirst(basename($this->getId()));
			if($this->getAction()!==null && strcasecmp($this->getAction()->getId(),$this->defaultAction))
				return $this->_pageTitle=Yii::app()->name.' - '.ucfirst($this->getAction()->getId()).' '.$name;
			else
				return $this->_pageTitle=Yii::app()->name.' - '.$name;
		}
	}
	public function setPageTitle($value)
	{
		$this->_pageTitle=$value;
	}
	public function redirect($url,$terminate=true,$statusCode=302)
	{
		if(is_array($url))
		{
			$route=isset($url[0]) ? $url[0] : '';
			$url=$this->createUrl($route,array_splice($url,1));
		}
		Yii::app()->getRequest()->redirect($url,$terminate,$statusCode);
	}
	public function refresh($terminate=true,$anchor='')
	{
		$this->redirect(Yii::app()->getRequest()->getUrl().$anchor,$terminate);
	}
	public function recordCachingAction($context,$method,$params)
	{
		if($this->_cachingStack) // record only when there is an active output cache
		{
			foreach($this->_cachingStack as $cache)
				$cache->recordAction($context,$method,$params);
		}
	}
	public function getCachingStack($createIfNull=true)
	{
		if(!$this->_cachingStack)
			$this->_cachingStack=new CStack;
		return $this->_cachingStack;
	}
	public function isCachingStackEmpty()
	{
		return $this->_cachingStack===null || !$this->_cachingStack->getCount();
	}
	protected function beforeAction($action)
	{
		return true;
	}
	protected function afterAction($action)
	{
	}
	public function filterPostOnly($filterChain)
	{
		if(Yii::app()->getRequest()->getIsPostRequest())
			$filterChain->run();
		else
			throw new CHttpException(400,Yii::t('yii','Your request is not valid.'));
	}
	public function filterAjaxOnly($filterChain)
	{
		if(Yii::app()->getRequest()->getIsAjaxRequest())
			$filterChain->run();
		else
			throw new CHttpException(400,Yii::t('yii','Your request is not valid.'));
	}
	public function filterAccessControl($filterChain)
	{
		$filter=new CAccessControlFilter;
		$filter->setRules($this->accessRules());
		$filter->filter($filterChain);
	}
	public function paginate($itemCount,$pageSize=null,$pageVar=null)
	{
		$pages=new CPagination($itemCount);
		if($pageSize!==null)
			$pages->pageSize=$pageSize;
		if($pageVar!==null)
			$pages->pageVar=$pageVar;
		return $pages;
	}
	public function getPageState($name,$defaultValue=null)
	{
		if($this->_pageStates===null)
			$this->_pageStates=$this->loadPageStates();
		return isset($this->_pageStates[$name])?$this->_pageStates[$name]:$defaultValue;
	}
	public function setPageState($name,$value,$defaultValue=null)
	{
		if($this->_pageStates===null)
			$this->_pageStates=$this->loadPageStates();
		if($value===$defaultValue)
			unset($this->_pageStates[$name]);
		else
			$this->_pageStates[$name]=$value;
		$params=func_get_args();
		$this->recordCachingAction('','setPageState',$params);
	}
	public function clearPageStates()
	{
		$this->_pageStates=array();
	}
	protected function loadPageStates()
	{
		if(isset($_POST[self::STATE_INPUT_NAME]) && !empty($_POST[self::STATE_INPUT_NAME]))
		{
			if(($data=base64_decode($_POST[self::STATE_INPUT_NAME]))!==false)
			{
				if(extension_loaded('zlib'))
					$data=@gzuncompress($data);
				if(($data=Yii::app()->getSecurityManager()->validateData($data))!==false)
					return unserialize($data);
			}
		}
		return array();
	}
	protected function savePageStates($states,&$output)
	{
		$data=Yii::app()->getSecurityManager()->hashData(serialize($states));
		if(extension_loaded('zlib'))
			$data=gzcompress($data);
		$value=base64_encode($data);
		$output=str_replace(CHtml::pageStateField(''),CHtml::pageStateField($value),$output);
	}
}
abstract class CAction extends CComponent implements IAction
{
	private $_id;
	private $_controller;
	public function __construct($controller,$id)
	{
		$this->_controller=$controller;
		$this->_id=$id;
	}
	public function getController()
	{
		return $this->_controller;
	}
	public function getId()
	{
		return $this->_id;
	}
}
class CInlineAction extends CAction
{
	public function run()
	{
		$method='action'.$this->getId();
		$this->getController()->$method();
	}
}
class CWebUser extends CApplicationComponent implements IWebUser
{
	const FLASH_KEY_PREFIX='Yii.CWebUser.flash.';
	const FLASH_COUNTERS='Yii.CWebUser.flash.counters';
	const STATES_VAR='__states';
	public $allowAutoLogin=false;
	public $guestName='Guest';
	public $loginUrl=array('site/login');
	public $identityCookie;
	private $_keyPrefix;
	private $_access=array();
	public function __get($name)
	{
		if($this->hasState($name))
			return $this->getState($name);
		else
			return parent::__get($name);
	}
	public function __set($name,$value)
	{
		if($this->hasState($name))
			$this->setState($name,$value);
		else
			parent::__set($name,$value);
	}
	public function __isset($name)
	{
		if($this->hasState($name))
			return $this->getState($name)!==null;
		else
			return parent::__isset($name);
	}
	public function __unset($name)
	{
		if($this->hasState($name))
			$this->setState($name,null);
		else
			parent::__unset($name);
	}
	public function init()
	{
		parent::init();
		Yii::app()->getSession()->open();
		if($this->getIsGuest() && $this->allowAutoLogin)
			$this->restoreFromCookie();
		$this->updateFlash();
	}
	public function login($identity,$duration=0)
	{
		$this->changeIdentity($identity->getId(),$identity->getName(),$identity->getPersistentStates());
		if($duration>0)
		{
			if($this->allowAutoLogin)
				$this->saveToCookie($duration);
			else
				throw new CException(Yii::t('yii','{class}.allowAutoLogin must be set true in order to use cookie-based authentication.',
					array('{class}'=>get_class($this))));
		}
	}
	public function logout($destroySession=true)
	{
		if($this->allowAutoLogin)
			Yii::app()->getRequest()->getCookies()->remove($this->getStateKeyPrefix());
		if($destroySession)
			Yii::app()->getSession()->destroy();
		else
			$this->clearStates();
	}
	public function getIsGuest()
	{
		return $this->getState('__id')===null;
	}
	public function getId()
	{
		return $this->getState('__id');
	}
	public function setId($value)
	{
		$this->setState('__id',$value);
	}
	public function getName()
	{
		if(($name=$this->getState('__name'))!==null)
			return $name;
		else
			return $this->guestName;
	}
	public function setName($value)
	{
		$this->setState('__name',$value);
	}
	public function getReturnUrl()
	{
		return $this->getState('__returnUrl',Yii::app()->getRequest()->getScriptUrl());
	}
	public function setReturnUrl($value)
	{
		$this->setState('__returnUrl',$value);
	}
	public function loginRequired()
	{
		$app=Yii::app();
		$request=$app->getRequest();
		$this->setReturnUrl($request->getUrl());
		if(($url=$this->loginUrl)!==null)
		{
			if(is_array($url))
			{
				$route=isset($url[0]) ? $url[0] : $app->defaultController;
				$url=$app->createUrl($route,array_splice($url,1));
			}
			$request->redirect($url);
		}
		else
			throw new CHttpException(403,Yii::t('yii','Login Required'));
	}
	protected function restoreFromCookie()
	{
		$app=Yii::app();
		$cookie=$app->getRequest()->getCookies()->itemAt($this->getStateKeyPrefix());
		if($cookie && !empty($cookie->value) && ($data=$app->getSecurityManager()->validateData($cookie->value))!==false)
		{
			$data=unserialize($data);
			if(isset($data[0],$data[1],$data[2]))
			{
				list($id,$name,$states)=$data;
				$this->changeIdentity($id,$name,$states);
			}
		}
	}
	protected function saveToCookie($duration)
	{
		$app=Yii::app();
		$cookie=$this->createIdentityCookie($this->getStateKeyPrefix());
		$cookie->expire=time()+$duration;
		$data=array(
			$this->getId(),
			$this->getName(),
			$this->saveIdentityStates(),
		);
		$cookie->value=$app->getSecurityManager()->hashData(serialize($data));
		$app->getRequest()->getCookies()->add($cookie->name,$cookie);
	}
	protected function createIdentityCookie($name)
	{
		$cookie=new CHttpCookie($name,'');
		if(is_array($this->identityCookie))
		{
			foreach($this->identityCookie as $name=>$value)
				$cookie->$name=$value;
		}
		return $cookie;
	}
	public function getStateKeyPrefix()
	{
		if($this->_keyPrefix!==null)
			return $this->_keyPrefix;
		else
			return $this->_keyPrefix=md5('Yii.'.get_class($this).'.'.Yii::app()->getId());
	}
	public function setStateKeyPrefix($value)
	{
		$this->_keyPrefix=$value;
	}
	public function getState($key,$defaultValue=null)
	{
		$key=$this->getStateKeyPrefix().$key;
		return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
	}
	public function setState($key,$value,$defaultValue=null)
	{
		$key=$this->getStateKeyPrefix().$key;
		if($value===$defaultValue)
			unset($_SESSION[$key]);
		else
			$_SESSION[$key]=$value;
	}
	public function hasState($key)
	{
		$key=$this->getStateKeyPrefix().$key;
		return isset($_SESSION[$key]);
	}
	public function clearStates()
	{
		$keys=array_keys($_SESSION);
		$prefix=$this->getStateKeyPrefix();
		$n=strlen($prefix);
		foreach($keys as $key)
		{
			if(!strncmp($key,$prefix,$n))
				unset($_SESSION[$key]);
		}
	}
	public function getFlash($key,$defaultValue=null,$delete=true)
	{
		$value=$this->getState(self::FLASH_KEY_PREFIX.$key,$defaultValue);
		if($delete)
			$this->setFlash($key,null);
		return $value;
	}
	public function setFlash($key,$value,$defaultValue=null)
	{
		$this->setState(self::FLASH_KEY_PREFIX.$key,$value,$defaultValue);
		$counters=$this->getState(self::FLASH_COUNTERS,array());
		if($value===$defaultValue)
			unset($counters[$key]);
		else
			$counters[$key]=0;
		$this->setState(self::FLASH_COUNTERS,$counters,array());
	}
	public function hasFlash($key)
	{
		return $this->getFlash($key, null, false)!==null;
	}
	protected function changeIdentity($id,$name,$states)
	{
		$this->setId($id);
		$this->setName($name);
		$this->loadIdentityStates($states);
	}
	protected function saveIdentityStates()
	{
		$states=array();
		foreach($this->getState(self::STATES_VAR,array()) as $name=>$dummy)
			$states[$name]=$this->getState($name);
		return $states;
	}
	protected function loadIdentityStates($states)
	{
		$names=array();
		if(is_array($states))
		{
			foreach($states as $name=>$value)
			{
				$this->setState($name,$value);
				$names[$name]=true;
			}
		}
		$this->setState(self::STATES_VAR,$names);
	}
	protected function updateFlash()
	{
		$counters=$this->getState(self::FLASH_COUNTERS);
		if(!is_array($counters))
			return;
		foreach($counters as $key=>$count)
		{
			if($count)
			{
				unset($counters[$key]);
				$this->setState(self::FLASH_KEY_PREFIX.$key,null);
			}
			else
				$counters[$key]++;
		}
		$this->setState(self::FLASH_COUNTERS,$counters,array());
	}
	public function checkAccess($operation,$params=array(),$allowCaching=true)
	{
		if($allowCaching && isset($this->_access[$operation]))
			return $this->_access[$operation];
		else
			return $this->_access[$operation]=Yii::app()->getAuthManager()->checkAccess($operation,$this->getId(),$params);
	}
}
class CHttpSession extends CApplicationComponent implements IteratorAggregate,ArrayAccess,Countable
{
	public $autoStart=true;
	public function init()
	{
		parent::init();
		if($this->autoStart)
			$this->open();
		register_shutdown_function(array($this,'close'));
	}
	public function getUseCustomStorage()
	{
		return false;
	}
	public function open()
	{
		if($this->getUseCustomStorage())
			@session_set_save_handler(array($this,'openSession'),array($this,'closeSession'),array($this,'readSession'),array($this,'writeSession'),array($this,'destroySession'),array($this,'gcSession'));
		@session_start();
	}
	public function close()
	{
		if(session_id()!=='')
			@session_write_close();
	}
	public function destroy()
	{
		if(session_id()!=='')
		{
			@session_unset();
			@session_destroy();
		}
	}
	public function getIsStarted()
	{
		return session_id()!=='';
	}
	public function getSessionID()
	{
		return session_id();
	}
	public function setSessionID($value)
	{
		session_id($value);
	}
	public function getSessionName()
	{
		return session_name();
	}
	public function setSessionName($value)
	{
		session_name($value);
	}
	public function getSavePath()
	{
		return session_save_path();
	}
	public function setSavePath($value)
	{
		if(is_dir($value))
			session_save_path($value);
		else
			throw new CException(Yii::t('yii','CHttpSession.savePath "{path}" is not a valid directory.',
				array('{path}'=>$value)));
	}
	public function getCookieParams()
	{
		return session_get_cookie_params();
	}
	public function setCookieParams($value)
	{
		$data=session_get_cookie_params();
		extract($data);
		extract($value);
		if(isset($httponly))
			session_set_cookie_params($lifetime,$path,$domain,$secure,$httponly);
		else
			session_set_cookie_params($lifetime,$path,$domain,$secure);
	}
	public function getCookieMode()
	{
		if(ini_get('session.use_cookies')==='0')
			return 'none';
		else if(ini_get('session.use_only_cookies')==='0')
			return 'allow';
		else
			return 'only';
	}
	public function setCookieMode($value)
	{
		if($value==='none')
			ini_set('session.use_cookies','0');
		else if($value==='allow')
		{
			ini_set('session.use_cookies','1');
			ini_set('session.use_only_cookies','0');
		}
		else if($value==='only')
		{
			ini_set('session.use_cookies','1');
			ini_set('session.use_only_cookies','1');
		}
		else
			throw new CException(Yii::t('yii','CHttpSession.cookieMode can only be "none", "allow" or "only".'));
	}
	public function getGCProbability()
	{
		return (int)ini_get('session.gc_probability');
	}
	public function setGCProbability($value)
	{
		$value=(int)$value;
		if($value>=0 && $value<=100)
		{
			ini_set('session.gc_probability',$value);
			ini_set('session.gc_divisor','100');
		}
		else
			throw new CException(Yii::t('yii','CHttpSession.gcProbability "{value}" is invalid. It must be an integer between 0 and 100.',
				array('{value}'=>$value)));
	}
	public function getUseTransparentSessionID()
	{
		return ini_get('session.use_trans_sid')==1;
	}
	public function setUseTransparentSessionID($value)
	{
		ini_set('session.use_trans_sid',$value?'1':'0');
	}
	public function getTimeout()
	{
		return (int)ini_get('session.gc_maxlifetime');
	}
	public function setTimeout($value)
	{
		ini_set('session.gc_maxlifetime',$value);
	}
	public function openSession($savePath,$sessionName)
	{
		return true;
	}
	public function closeSession()
	{
		return true;
	}
	public function readSession($id)
	{
		return '';
	}
	public function writeSession($id,$data)
	{
		return true;
	}
	public function destroySession($id)
	{
		return true;
	}
	public function gcSession($maxLifetime)
	{
		return true;
	}
	//------ The following methods enable CHttpSession to be CMap-like -----
	public function getIterator()
	{
		return new CHttpSessionIterator;
	}
	public function getCount()
	{
		return count($_SESSION);
	}
	public function count()
	{
		return $this->getCount();
	}
	public function getKeys()
	{
		return array_keys($_SESSION);
	}
	public function itemAt($key)
	{
		return isset($_SESSION[$key]) ? $_SESSION[$key] : null;
	}
	public function add($key,$value)
	{
		$_SESSION[$key]=$value;
	}
	public function remove($key)
	{
		if(isset($_SESSION[$key]))
		{
			$value=$_SESSION[$key];
			unset($_SESSION[$key]);
			return $value;
		}
		else
			return null;
	}
	public function clear()
	{
		foreach(array_keys($_SESSION) as $key)
			unset($_SESSION[$key]);
	}
	public function contains($key)
	{
		return isset($_SESSION[$key]);
	}
	public function toArray()
	{
		return $_SESSION;
	}
	public function offsetExists($offset)
	{
		return isset($_SESSION[$offset]);
	}
	public function offsetGet($offset)
	{
		return isset($_SESSION[$offset]) ? $_SESSION[$offset] : null;
	}
	public function offsetSet($offset,$item)
	{
		$_SESSION[$offset]=$item;
	}
	public function offsetUnset($offset)
	{
		unset($_SESSION[$offset]);
	}
}
class CHtml
{
	const ID_PREFIX='yt';
	public static $errorSummaryCss='errorSummary';
	public static $errorMessageCss='errorMessage';
	public static $errorCss='error';
	public static $requiredCss='required';
	public static $beforeRequiredLabel='';
	public static $afterRequiredLabel=' <span class="required">*</span>';
	public static $scenario='';
	public static $count=0;
	public static function encode($text)
	{
		return htmlspecialchars($text,ENT_QUOTES,Yii::app()->charset);
	}
	public static function encodeArray($data)
	{
		$d=array();
		foreach($data as $key=>$value)
		{
			if(is_string($key))
				$key=htmlspecialchars($key,ENT_QUOTES,Yii::app()->charset);
			if(is_string($value))
				$value=htmlspecialchars($value,ENT_QUOTES,Yii::app()->charset);
			else if(is_array($value))
				$value=self::encodeArray($value);
			$d[$key]=$value;
		}
		return $d;
	}
	public static function tag($tag,$htmlOptions=array(),$content=false,$closeTag=true)
	{
		$html='<' . $tag . self::renderAttributes($htmlOptions);
		if($content===false)
			return $closeTag ? $html.' />' : $html.'>';
		else
			return $closeTag ? $html.'>'.$content.'</'.$tag.'>' : $html.'>'.$content;
	}
	public static function openTag($tag,$htmlOptions=array())
	{
		return '<' . $tag . self::renderAttributes($htmlOptions) . '>';
	}
	public static function closeTag($tag)
	{
		return '</'.$tag.'>';
	}
	public static function cdata($text)
	{
		return '<![CDATA[' . $text . ']]>';
	}
	public static function metaTag($content,$name=null,$httpEquiv=null,$options=array())
	{
		$options['content']=$content;
		if($name!==null)
			$options['name']=$name;
		if($httpEquiv!==null)
			$options['http-equiv']=$httpEquiv;
		return self::tag('meta',$options);
	}
	public static function linkTag($relation=null,$type=null,$href=null,$media=null,$options=array())
	{
		if($relation!==null)
			$options['rel']=$relation;
		if($type!==null)
			$options['type']=$type;
		if($href!==null)
			$options['href']=$href;
		if($media!==null)
			$options['media']=$media;
		return self::tag('link',$options);
	}
	public static function css($text,$media='')
	{
		if($media!=='')
			$media=' media="'.$media.'"';
		return "<style type=\"text/css\"{$media}>\n/*<![CDATA[*/\n{$text}\n/*]]>*/\n</style>";
	}
	public static function cssFile($url,$media='')
	{
		if($media!=='')
			$media=' media="'.$media.'"';
		return '<link rel="stylesheet" type="text/css" href="'.self::encode($url).'"'.$media.' />';
	}
	public static function script($text)
	{
		return "<script type=\"text/javascript\">\n/*<![CDATA[*/\n{$text}\n/*]]>*/\n</script>";
	}
	public static function scriptFile($url)
	{
		return '<script type="text/javascript" src="'.self::encode($url).'"></script>';
	}
	public static function form($action='',$method='post',$htmlOptions=array())
	{
		return self::beginForm($action,$method,$htmlOptions);
	}
	public static function beginForm($action='',$method='post',$htmlOptions=array())
	{
		$htmlOptions['action']=self::normalizeUrl($action);
		$htmlOptions['method']=$method;
		$form=self::tag('form',$htmlOptions,false,false);
		$request=Yii::app()->request;
		if($request->enableCsrfValidation)
		{
			$token=self::hiddenField($request->csrfTokenName,$request->getCsrfToken(),array('id'=>false));
			$form.="\n".self::tag('div',array('style'=>'display:none'),$token);
		}
		return $form;
	}
	public static function endForm()
	{
		return '</form>';
	}
	public static function statefulForm($action='',$method='post',$htmlOptions=array())
	{
		return self::form($action,$method,$htmlOptions)."\n".
			self::tag('div',array('style'=>'display:none'),self::pageStateField(''));
	}
	public static function pageStateField($value)
	{
		return '<input type="hidden" name="'.CController::STATE_INPUT_NAME.'" value="'.$value.'" />';
	}
	public static function link($text,$url='#',$htmlOptions=array())
	{
		if($url!=='')
			$htmlOptions['href']=self::normalizeUrl($url);
		self::clientChange('click',$htmlOptions);
		return self::tag('a',$htmlOptions,$text);
	}
	public static function mailto($text,$email='',$htmlOptions=array())
	{
		if($email==='')
			$email=$text;
		return self::link($text,'mailto:'.$email,$htmlOptions);
	}
	public static function image($src,$alt='',$htmlOptions=array())
	{
		$htmlOptions['src']=$src;
		$htmlOptions['alt']=$alt;
		return self::tag('img',$htmlOptions);
	}
	public static function button($label='button',$htmlOptions=array())
	{
		if(!isset($htmlOptions['name']))
			$htmlOptions['name']=self::ID_PREFIX.self::$count++;
		if(!isset($htmlOptions['type']))
			$htmlOptions['type']='button';
		if(!isset($htmlOptions['value']))
			$htmlOptions['value']=$label;
		self::clientChange('click',$htmlOptions);
		return self::tag('input',$htmlOptions);
	}
	public static function htmlButton($label='button',$htmlOptions=array())
	{
		if(!isset($htmlOptions['name']))
			$htmlOptions['name']=self::ID_PREFIX.self::$count++;
		if(!isset($htmlOptions['type']))
			$htmlOptions['type']='button';
		self::clientChange('click',$htmlOptions);
		return self::tag('button',$htmlOptions,$label);
	}
	public static function submitButton($label='submit',$htmlOptions=array())
	{
		$htmlOptions['type']='submit';
		return self::button($label,$htmlOptions);
	}
	public static function resetButton($label='reset',$htmlOptions=array())
	{
		$htmlOptions['type']='reset';
		return self::button($label,$htmlOptions);
	}
	public static function imageButton($src,$htmlOptions=array())
	{
		$htmlOptions['src']=$src;
		$htmlOptions['type']='image';
		return self::button('submit',$htmlOptions);
	}
	public static function linkButton($label='submit',$htmlOptions=array())
	{
		if(!isset($htmlOptions['submit']))
			$htmlOptions['submit']=isset($htmlOptions['href']) ? $htmlOptions['href'] : '';
		return self::link($label,'#',$htmlOptions);
	}
	public static function label($label,$for,$htmlOptions=array())
	{
		if($for===false)
			unset($htmlOptions['for']);
		else
			$htmlOptions['for']=$for;
		if(isset($htmlOptions['required']))
		{
			if($htmlOptions['required'])
			{
				if(isset($htmlOptions['class']))
					$htmlOptions['class'].=' '.self::$requiredCss;
				else
					$htmlOptions['class']=self::$requiredCss;
				$label=self::$beforeRequiredLabel.$label.self::$afterRequiredLabel;
			}
			unset($htmlOptions['required']);
		}
		return self::tag('label',$htmlOptions,$label);
	}
	public static function textField($name,$value='',$htmlOptions=array())
	{
		self::clientChange('change',$htmlOptions);
		return self::inputField('text',$name,$value,$htmlOptions);
	}
	public static function hiddenField($name,$value='',$htmlOptions=array())
	{
		return self::inputField('hidden',$name,$value,$htmlOptions);
	}
	public static function passwordField($name,$value='',$htmlOptions=array())
	{
		self::clientChange('change',$htmlOptions);
		return self::inputField('password',$name,$value,$htmlOptions);
	}
	public static function fileField($name,$value='',$htmlOptions=array())
	{
		return self::inputField('file',$name,$value,$htmlOptions);
	}
	public static function textArea($name,$value='',$htmlOptions=array())
	{
		$htmlOptions['name']=$name;
		if(!isset($htmlOptions['id']))
			$htmlOptions['id']=self::getIdByName($name);
		self::clientChange('change',$htmlOptions);
		return self::tag('textarea',$htmlOptions,isset($htmlOptions['encode']) && !$htmlOptions['encode'] ? $value : self::encode($value));
	}
	public static function radioButton($name,$checked=false,$htmlOptions=array())
	{
		if($checked)
			$htmlOptions['checked']='checked';
		else
			unset($htmlOptions['checked']);
		$value=isset($htmlOptions['value']) ? $htmlOptions['value'] : 1;
		self::clientChange('click',$htmlOptions);
		return self::inputField('radio',$name,$value,$htmlOptions);
	}
	public static function checkBox($name,$checked=false,$htmlOptions=array())
	{
		if($checked)
			$htmlOptions['checked']='checked';
		else
			unset($htmlOptions['checked']);
		$value=isset($htmlOptions['value']) ? $htmlOptions['value'] : 1;
		self::clientChange('click',$htmlOptions);
		return self::inputField('checkbox',$name,$value,$htmlOptions);
	}
	public static function dropDownList($name,$select,$data,$htmlOptions=array())
	{
		$htmlOptions['name']=$name;
		if(!isset($htmlOptions['id']))
			$htmlOptions['id']=self::getIdByName($name);
		self::clientChange('change',$htmlOptions);
		$options="\n".self::listOptions($select,$data,$htmlOptions);
		return self::tag('select',$htmlOptions,$options);
	}
	public static function listBox($name,$select,$data,$htmlOptions=array())
	{
		if(!isset($htmlOptions['size']))
			$htmlOptions['size']=4;
		if(isset($htmlOptions['multiple']))
		{
			if(substr($name,-2)!=='[]')
				$name.='[]';
		}
		return self::dropDownList($name,$select,$data,$htmlOptions);
	}
	public static function checkBoxList($name,$select,$data,$htmlOptions=array())
	{
		$template=isset($htmlOptions['template'])?$htmlOptions['template']:'{input} {label}';
		$separator=isset($htmlOptions['separator'])?$htmlOptions['separator']:"<br/>\n";
		unset($htmlOptions['template'],$htmlOptions['separator']);
		if(substr($name,-2)!=='[]')
			$name.='[]';
		if(isset($htmlOptions['checkAll']))
		{
			$checkAllLabel=$htmlOptions['checkAll'];
			$checkAllLast=isset($htmlOptions['checkAllLast']) && $htmlOptions['checkAllLast'];
		}
		unset($htmlOptions['checkAll'],$htmlOptions['checkAllLast']);
		$labelOptions=isset($htmlOptions['labelOptions'])?$htmlOptions['labelOptions']:array();
		unset($htmlOptions['labelOptions']);
		$items=array();
		$baseID=self::getIdByName($name);
		$id=0;
		$checkAll=true;
		foreach($data as $value=>$label)
		{
			$checked=!is_array($select) && !strcmp($value,$select) || is_array($select) && in_array($value,$select);
			$checkAll=$checkAll && $checked;
			$htmlOptions['value']=$value;
			$htmlOptions['id']=$baseID.'_'.$id++;
			$option=self::checkBox($name,$checked,$htmlOptions);
			$label=self::label($label,$htmlOptions['id'],$labelOptions);
			$items[]=strtr($template,array('{input}'=>$option,'{label}'=>$label));
		}
		if(isset($checkAllLabel))
		{
			$htmlOptions['value']=1;
			$htmlOptions['id']=$id=$baseID.'_all';
			$option=self::checkBox($id,$checkAll,$htmlOptions);
			$label=self::label($checkAllLabel,$id,$labelOptions);
			$item=strtr($template,array('{input}'=>$option,'{label}'=>$label));
			if($checkAllLast)
				$items[]=$item;
			else
				array_unshift($items,$item);
			$name=strtr($name,array('['=>'\\[',']'=>'\\]'));
			$js=<<<EOD
jQuery('#$id').click(function() {
	var checked=this.checked;
	jQuery("input[name='$name']").each(function() {
		this.checked=checked;
	});
});
jQuery("input[name='$name']").click(function() {
	jQuery('#$id').attr('checked', jQuery("input[name='$name']").length==jQuery("input[name='$name'][checked=true]").length);
});
EOD;
			$cs=Yii::app()->getClientScript();
			$cs->registerCoreScript('jquery');
			$cs->registerScript($id,$js);
		}
		return implode($separator,$items);
	}
	public static function radioButtonList($name,$select,$data,$htmlOptions=array())
	{
		$template=isset($htmlOptions['template'])?$htmlOptions['template']:'{input} {label}';
		$separator=isset($htmlOptions['separator'])?$htmlOptions['separator']:"<br/>\n";
		unset($htmlOptions['template'],$htmlOptions['separator']);
		$labelOptions=isset($htmlOptions['labelOptions'])?$htmlOptions['labelOptions']:array();
		unset($htmlOptions['labelOptions']);
		$items=array();
		$baseID=self::getIdByName($name);
		$id=0;
		foreach($data as $value=>$label)
		{
			$checked=!strcmp($value,$select);
			$htmlOptions['value']=$value;
			$htmlOptions['id']=$baseID.'_'.$id++;
			$option=self::radioButton($name,$checked,$htmlOptions);
			$label=self::label($label,$htmlOptions['id'],$labelOptions);
			$items[]=strtr($template,array('{input}'=>$option,'{label}'=>$label));
		}
		return implode($separator,$items);
	}
	public static function ajaxLink($text,$url,$ajaxOptions=array(),$htmlOptions=array())
	{
		if(!isset($htmlOptions['href']))
			$htmlOptions['href']='#';
		$ajaxOptions['url']=$url;
		$htmlOptions['ajax']=$ajaxOptions;
		self::clientChange('click',$htmlOptions);
		return self::tag('a',$htmlOptions,$text);
	}
	public static function ajaxButton($label,$url,$ajaxOptions=array(),$htmlOptions=array())
	{
		$ajaxOptions['url']=$url;
		$htmlOptions['ajax']=$ajaxOptions;
		return self::button($label,$htmlOptions);
	}
	public static function ajaxSubmitButton($label,$url,$ajaxOptions=array(),$htmlOptions=array())
	{
		$ajaxOptions['type']='POST';
		return self::ajaxButton($label,$url,$ajaxOptions,$htmlOptions);
	}
	public static function ajax($options)
	{
		Yii::app()->getClientScript()->registerCoreScript('jquery');
		if(!isset($options['url']))
			$options['url']='js:location.href';
		else
			$options['url']=self::normalizeUrl($options['url']);
		if(!isset($options['cache']))
			$options['cache']=false;
		if(!isset($options['data']) && isset($options['type']))
			$options['data']='js:jQuery(this).parents("form").serialize()';
		foreach(array('beforeSend','complete','error','success') as $name)
		{
			if(isset($options[$name]) && strpos($options[$name],'js:')!==0)
				$options[$name]='js:'.$options[$name];
		}
		if(isset($options['update']))
		{
			if(!isset($options['success']))
				$options['success']='js:function(html){jQuery("'.$options['update'].'").html(html)}';
			unset($options['update']);
		}
		if(isset($options['replace']))
		{
			if(!isset($options['success']))
				$options['success']='js:function(html){jQuery("'.$options['replace'].'").replaceWith(html)}';
			unset($options['replace']);
		}
		return 'jQuery.ajax('.CJavaScript::encode($options).');';
	}
	public static function asset($path,$hashByName=false)
	{
		return Yii::app()->getAssetManager()->publish($path,$hashByName);
	}
	public static function normalizeUrl($url)
	{
		if(is_array($url))
		{
			if(isset($url[0]))
			{
				if(($c=Yii::app()->getController())!==null)
					$url=$c->createUrl($url[0],array_splice($url,1));
				else
					$url=Yii::app()->createUrl($url[0],array_splice($url,1));
			}
			else
				$url='';
		}
		return $url==='' ? Yii::app()->getRequest()->getUrl() : $url;
	}
	protected static function inputField($type,$name,$value,$htmlOptions)
	{
		$htmlOptions['type']=$type;
		$htmlOptions['value']=$value;
		$htmlOptions['name']=$name;
		if(!isset($htmlOptions['id']))
			$htmlOptions['id']=self::getIdByName($name);
		else if($htmlOptions['id']===false)
			unset($htmlOptions['id']);
		return self::tag('input',$htmlOptions);
	}
	public static function activeLabel($model,$attribute,$htmlOptions=array())
	{
		if(isset($htmlOptions['for']))
		{
			$for=$htmlOptions['for'];
			unset($htmlOptions['for']);
		}
		else
			$for=self::getIdByName(self::resolveName($model,$attribute));
		if(isset($htmlOptions['label']))
		{
			$label=$htmlOptions['label'];
			unset($htmlOptions['label']);
		}
		else
			$label=$model->getAttributeLabel($attribute);
		if($model->hasErrors($attribute))
			self::addErrorCss($htmlOptions);
		return self::label($label,$for,$htmlOptions);
	}
	public static function activeLabelEx($model,$attribute,$htmlOptions=array())
	{
		$realAttribute=$attribute;
		self::resolveName($model,$attribute); // strip off square brackets if any
		$htmlOptions['required']=$model->isAttributeRequired($attribute,self::$scenario);
		return self::activeLabel($model,$realAttribute,$htmlOptions);
	}
	public static function activeTextField($model,$attribute,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		self::clientChange('change',$htmlOptions);
		return self::activeInputField('text',$model,$attribute,$htmlOptions);
	}
	public static function activeHiddenField($model,$attribute,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		return self::activeInputField('hidden',$model,$attribute,$htmlOptions);
	}
	public static function activePasswordField($model,$attribute,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		self::clientChange('change',$htmlOptions);
		return self::activeInputField('password',$model,$attribute,$htmlOptions);
	}
	public static function activeTextArea($model,$attribute,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		self::clientChange('change',$htmlOptions);
		if($model->hasErrors($attribute))
			self::addErrorCss($htmlOptions);
		return self::tag('textarea',$htmlOptions,isset($htmlOptions['encode']) && !$htmlOptions['encode'] ? $model->$attribute : self::encode($model->$attribute));
	}
	public static function activeFileField($model,$attribute,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		// add a hidden field so that if a model only has a file field, we can
		// still use isset($_POST[$modelClass]) to detect if the input is submitted
		return self::hiddenField($htmlOptions['name'],'',array('id'=>self::ID_PREFIX.$htmlOptions['id']))
			. self::activeInputField('file',$model,$attribute,$htmlOptions);
	}
	public static function activeRadioButton($model,$attribute,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		if(!isset($htmlOptions['value']))
			$htmlOptions['value']=1;
		if(!isset($htmlOptions['checked']) && $model->$attribute==$htmlOptions['value'])
			$htmlOptions['checked']='checked';
		self::clientChange('click',$htmlOptions);
		if(array_key_exists('uncheckValue',$htmlOptions))
		{
			$uncheck=$htmlOptions['uncheckValue'];
			unset($htmlOptions['uncheckValue']);
		}
		else
			$uncheck='0';
		$hidden=$uncheck!==null ? self::hiddenField($htmlOptions['name'],$uncheck,array('id'=>self::ID_PREFIX.$htmlOptions['id'])) : '';
		// add a hidden field so that if the radio button is not selected, it still submits a value
		return $hidden . self::activeInputField('radio',$model,$attribute,$htmlOptions);
	}
	public static function activeCheckBox($model,$attribute,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		if(!isset($htmlOptions['value']))
			$htmlOptions['value']=1;
		if(!isset($htmlOptions['checked']) && $model->$attribute==$htmlOptions['value'])
			$htmlOptions['checked']='checked';
		self::clientChange('click',$htmlOptions);
		if(array_key_exists('uncheckValue',$htmlOptions))
		{
			$uncheck=$htmlOptions['uncheckValue'];
			unset($htmlOptions['uncheckValue']);
		}
		else
			$uncheck='0';
		$hidden=$uncheck!==null ? self::hiddenField($htmlOptions['name'],$uncheck,array('id'=>self::ID_PREFIX.$htmlOptions['id'])) : '';
		return $hidden . self::activeInputField('checkbox',$model,$attribute,$htmlOptions);
	}
	public static function activeDropDownList($model,$attribute,$data,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		$selection=$model->$attribute;
		$options="\n".self::listOptions($selection,$data,$htmlOptions);
		self::clientChange('change',$htmlOptions);
		if($model->hasErrors($attribute))
			self::addErrorCss($htmlOptions);
		if(isset($htmlOptions['multiple']))
		{
			if(substr($htmlOptions['name'],-2)!=='[]')
				$htmlOptions['name'].='[]';
		}
		return self::tag('select',$htmlOptions,$options);
	}
	public static function activeListBox($model,$attribute,$data,$htmlOptions=array())
	{
		if(!isset($htmlOptions['size']))
			$htmlOptions['size']=4;
		return self::activeDropDownList($model,$attribute,$data,$htmlOptions);
	}
	public static function activeCheckBoxList($model,$attribute,$data,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		$selection=$model->$attribute;
		if($model->hasErrors($attribute))
			self::addErrorCss($htmlOptions);
		$name=$htmlOptions['name'];
		unset($htmlOptions['name']);
		return self::hiddenField($name,'',array('id'=>self::ID_PREFIX.$htmlOptions['id']))
			. self::checkBoxList($name,$selection,$data,$htmlOptions);
	}
	public static function activeRadioButtonList($model,$attribute,$data,$htmlOptions=array())
	{
		self::resolveNameID($model,$attribute,$htmlOptions);
		$selection=$model->$attribute;
		if($model->hasErrors($attribute))
			self::addErrorCss($htmlOptions);
		$name=$htmlOptions['name'];
		unset($htmlOptions['name']);
		return self::hiddenField($name,'',array('id'=>self::ID_PREFIX.$htmlOptions['id']))
			. self::radioButtonList($name,$selection,$data,$htmlOptions);
	}
	public static function getActiveId($model,$attribute)
	{
		return self::activeId($model,$attribute);
	}
	public static function errorSummary($model,$header=null,$footer=null,$htmlOptions=array())
	{
		$content='';
		if(!is_array($model))
			$model=array($model);
		foreach($model as $m)
		{
			foreach($m->getErrors() as $errors)
			{
				foreach($errors as $error)
				{
					if($error!='')
						$content.="<li>$error</li>\n";
				}
			}
		}
		if($content!=='')
		{
			if($header===null)
				$header='<p>'.Yii::t('yii','Please fix the following input errors:').'</p>';
			if(!isset($htmlOptions['class']))
				$htmlOptions['class']=self::$errorSummaryCss;
			return self::tag('div',$htmlOptions,$header."\n<ul>\n$content</ul>".$footer);
		}
		else
			return '';
	}
	public static function error($model,$attribute,$htmlOptions=array())
	{
		$error=$model->getError($attribute);
		if($error!='')
		{
			if(!isset($htmlOptions['class']))
				$htmlOptions['class']=self::$errorMessageCss;
			return self::tag('div',$htmlOptions,$error);
		}
		else
			return '';
	}
	public static function listData($models,$valueField,$textField,$groupField='')
	{
		$listData=array();
		if($groupField==='')
		{
			foreach($models as $model)
			{
				$value=self::value($model,$valueField);
				$text=self::value($model,$textField);
				$listData[$value]=$text;
			}
		}
		else
		{
			foreach($models as $model)
			{
				$group=self::value($model,$groupField);
				$value=self::value($model,$valueField);
				$text=self::value($model,$textField);
				$listData[$group][$value]=$text;
			}
		}
		return $listData;
	}
	public static function value($model,$attribute,$defaultValue=null)
	{
		foreach(explode('.',$attribute) as $name)
		{
			if(is_object($model))
				$model=$model->$name;
			else if(is_array($model) && isset($model[$name]))
				$model=$model[$name];
			else
				return $defaultValue;
		}
		return $model;
	}
	public static function getIdByName($name)
	{
		return str_replace(array('[]', '][', '[', ']'), array('', '_', '_', ''), $name);
	}
	public static function activeId($model,$attribute)
	{
		return self::getIdByName(self::activeName($model,$attribute));
	}
	public static function activeName($model,$attribute)
	{
		$a=$attribute; // because the attribute name may be changed by resolveName
		return self::resolveName($model,$a);
	}
	protected static function activeInputField($type,$model,$attribute,$htmlOptions)
	{
		$htmlOptions['type']=$type;
		if($type==='file')
			unset($htmlOptions['value']);
		else if(!isset($htmlOptions['value']))
			$htmlOptions['value']=$model->$attribute;
		if($model->hasErrors($attribute))
			self::addErrorCss($htmlOptions);
		return self::tag('input',$htmlOptions);
	}
	public static function listOptions($selection,$listData,&$htmlOptions)
	{
		$raw=isset($htmlOptions['encode']) && !$htmlOptions['encode'];
		$content='';
		if(isset($htmlOptions['prompt']))
		{
			$content.='<option value="">'.($raw?$htmlOptions['prompt'] : self::encode($htmlOptions['prompt']))."</option>\n";
			unset($htmlOptions['prompt']);
		}
		if(isset($htmlOptions['empty']))
		{
			if(!is_array($htmlOptions['empty']))
				$htmlOptions['empty']=array(''=>$htmlOptions['empty']);
			foreach($htmlOptions['empty'] as $value=>$label)
			{
				if($raw)
					$content.='<option value="'.$value.'">'.$label."</option>\n";
				else
					$content.='<option value="'.self::encode($value).'">'.self::encode($label)."</option>\n";
			}
			unset($htmlOptions['empty']);
		}
		if(isset($htmlOptions['options']))
		{
			$options=$htmlOptions['options'];
			unset($htmlOptions['options']);
		}
		else
			$options=array();
		foreach($listData as $key=>$value)
		{
			if(is_array($value))
			{
				$content.='<optgroup label="'.($raw?$key : self::encode($key))."\">\n";
				$dummy=array('options'=>$options);
				if(isset($htmlOptions['encode']))
					$dummy['encode']=$htmlOptions['encode'];
				$content.=self::listOptions($selection,$value,$dummy);
				$content.='</optgroup>'."\n";
			}
			else
			{
				$attributes=array('value'=>(string)$key, 'encode'=>!$raw);
				if(!is_array($selection) && !strcmp($key,$selection) || is_array($selection) && in_array($key,$selection))
					$attributes['selected']='selected';
				if(isset($options[$key]))
					$attributes=array_merge($attributes,$options[$key]);
				$content.=self::tag('option',$attributes,$raw?(string)$value : self::encode((string)$value))."\n";
			}
		}
		return $content;
	}
	protected static function clientChange($event,&$htmlOptions)
	{
		if(!isset($htmlOptions['submit']) && !isset($htmlOptions['confirm']) && !isset($htmlOptions['ajax']))
			return;
		if(isset($htmlOptions['return']) && $htmlOptions['return'])
			$return='return true';
		else
			$return='return false';
		if(isset($htmlOptions['on'.$event]))
		{
			$handler=trim($htmlOptions['on'.$event],';').';';
			unset($htmlOptions['on'.$event]);
		}
		else
			$handler='';
		if(isset($htmlOptions['id']))
			$id=$htmlOptions['id'];
		else
			$id=$htmlOptions['id']=isset($htmlOptions['name'])?$htmlOptions['name']:self::ID_PREFIX.self::$count++;
		$cs=Yii::app()->getClientScript();
		$cs->registerCoreScript('jquery');
		if(isset($htmlOptions['submit']))
		{
			$cs->registerCoreScript('yii');
			$request=Yii::app()->getRequest();
			if($request->enableCsrfValidation && isset($htmlOptions['csrf']) && $htmlOptions['csrf'])
				$htmlOptions['params'][$request->csrfTokenName]=$request->getCsrfToken();
			if(isset($htmlOptions['params']))
				$params=CJavaScript::encode($htmlOptions['params']);
			else
				$params='{}';
			if($htmlOptions['submit']!=='')
				$url=CJavaScript::quote(self::normalizeUrl($htmlOptions['submit']));
			else
				$url='';
			$handler.="jQuery.yii.submitForm(this,'$url',$params);{$return};";
		}
		if(isset($htmlOptions['ajax']))
			$handler.=self::ajax($htmlOptions['ajax'])."{$return};";
		if(isset($htmlOptions['confirm']))
		{
			$confirm='confirm(\''.CJavaScript::quote($htmlOptions['confirm']).'\')';
			if($handler!=='')
				$handler="if($confirm) {".$handler."} else return false;";
			else
				$handler="return $confirm;";
		}
		$cs->registerScript('Yii.CHtml.#'.$id,"jQuery('#$id').$event(function(){{$handler}});");
		unset($htmlOptions['params'],$htmlOptions['submit'],$htmlOptions['ajax'],$htmlOptions['confirm'],$htmlOptions['return'],$htmlOptions['csrf']);
	}
	public static function resolveNameID($model,&$attribute,&$htmlOptions)
	{
		$name=self::resolveName($model,$attribute);
		if(!isset($htmlOptions['name']))
			$htmlOptions['name']=$name;
		if(!isset($htmlOptions['id']))
			$htmlOptions['id']=self::getIdByName($htmlOptions['name']);
	}
	public static function resolveName($model,&$attribute)
	{
		if(($pos=strpos($attribute,'['))!==false)
		{
			$sub=substr($attribute,$pos);
			$attribute=substr($attribute,0,$pos);
			return get_class($model).$sub.'['.$attribute.']';
		}
		else
			return get_class($model).'['.$attribute.']';
	}
	protected static function addErrorCss(&$htmlOptions)
	{
		if(isset($htmlOptions['class']))
			$htmlOptions['class'].=' '.self::$errorCss;
		else
			$htmlOptions['class']=self::$errorCss;
	}
	protected static function renderAttributes($htmlOptions)
	{
		if($htmlOptions===array())
			return '';
		$html='';
		$raw=isset($htmlOptions['encode']) && !$htmlOptions['encode'];
		unset($htmlOptions['encode']);
		if($raw)
		{
			foreach($htmlOptions as $name=>$value)
				$html .= ' ' . $name . '="' . $value . '"';
		}
		else
		{
			foreach($htmlOptions as $name=>$value)
				$html .= ' ' . $name . '="' . self::encode($value) . '"';
		}
		return $html;
	}
}
class CWidget extends CBaseController
{
	public $actionPrefix;
	private static $_viewPaths;
	private static $_counter=0;
	private $_id;
	private $_owner;
	public static function actions()
	{
		return array();
	}
	public function __construct($owner=null)
	{
		$this->_owner=$owner===null?Yii::app()->getController():$owner;
	}
	public function getOwner()
	{
		return $this->_owner;
	}
	public function getId($autoGenerate=true)
	{
		if($this->_id!==null)
			return $this->_id;
		else if($autoGenerate)
			return $this->_id='yw'.self::$_counter++;
	}
	public function setId($value)
	{
		$this->_id=$value;
	}
	public function getController()
	{
		if($this->_owner instanceof CController)
			return $this->_owner;
		else
			return Yii::app()->getController();
	}
	public function init()
	{
	}
	public function run()
	{
	}
	public function getViewPath()
	{
		$className=get_class($this);
		if(isset(self::$_viewPaths[$className]))
			return self::$_viewPaths[$className];
		else
		{
			$class=new ReflectionClass(get_class($this));
			return self::$_viewPaths[$className]=dirname($class->getFileName()).DIRECTORY_SEPARATOR.'views';
		}
	}
	public function getViewFile($viewName)
	{
		if(($renderer=Yii::app()->getViewRenderer())!==null)
			$extension=$renderer->fileExtension;
		else
			$extension='.php';
		if(strpos($viewName,'.')) // a path alias
			$viewFile=Yii::getPathOfAlias($viewName).$extension;
		else
			$viewFile=$this->getViewPath().DIRECTORY_SEPARATOR.$viewName.$extension;
		return is_file($viewFile) ? Yii::app()->findLocalizedFile($viewFile) : false;
	}
	public function render($view,$data=null,$return=false)
	{
		if(($viewFile=$this->getViewFile($view))!==false)
			return $this->renderFile($viewFile,$data,$return);
		else
			throw new CException(Yii::t('yii','{widget} cannot find the view "{view}".',
				array('{widget}'=>get_class($this), '{view}'=>$view)));
	}
}
class CClientScript extends CApplicationComponent
{
	const POS_HEAD=0;
	const POS_BEGIN=1;
	const POS_END=2;
	const POS_LOAD=3;
	const POS_READY=4;
	public $enableJavaScript=true;
	public $scriptMap=array();
	protected $cssFiles=array();
	protected $scriptFiles=array();
	protected $scripts=array();
	private $_hasScripts=false;
	private $_packages;
	private $_dependencies;
	private $_baseUrl;
	private $_coreScripts=array();
	private $_css=array();
	private $_metas=array();
	private $_links=array();
	public function reset()
	{
		$this->_hasScripts=false;
		$this->_coreScripts=array();
		$this->cssFiles=array();
		$this->_css=array();
		$this->scriptFiles=array();
		$this->scripts=array();
		$this->_metas=array();
		$this->_links=array();
		$this->recordCachingAction('clientScript','reset',array());
	}
	public function render(&$output)
	{
		if(!$this->_hasScripts)
			return;
		$this->renderCoreScripts();
		if(!empty($this->scriptMap))
			$this->remapScripts();
		$this->renderHead($output);
		if($this->enableJavaScript)
		{
			$this->renderBodyBegin($output);
			$this->renderBodyEnd($output);
		}
	}
	protected function remapScripts()
	{
		$cssFiles=array();
		foreach($this->cssFiles as $url=>$media)
		{
			$name=basename($url);
			if(isset($this->scriptMap[$name]))
			{
				if($this->scriptMap[$name]!==false)
					$cssFiles[$this->scriptMap[$name]]=$media;
			}
			else if(isset($this->scriptMap['*.css']))
			{
				if($this->scriptMap['*.css']!==false)
					$cssFiles[$this->scriptMap['*.css']]=$media;
			}
			else
				$cssFiles[$url]=$media;
		}
		$this->cssFiles=$cssFiles;
		$jsFiles=array();
		foreach($this->scriptFiles as $position=>$scripts)
		{
			$jsFiles[$position]=array();
			foreach($scripts as $key=>$script)
			{
				$name=basename($script);
				if(isset($this->scriptMap[$name]))
				{
					if($this->scriptMap[$name]!==false)
						$jsFiles[$position][$this->scriptMap[$name]]=$this->scriptMap[$name];
				}
				else if(isset($this->scriptMap['*.js']))
				{
					if($this->scriptMap['*.js']!==false)
						$jsFiles[$position][$this->scriptMap['*.js']]=$this->scriptMap['*.js'];
				}
				else
					$jsFiles[$position][$key]=$script;
			}
		}
		$this->scriptFiles=$jsFiles;
	}
	public function renderCoreScripts()
	{
		if($this->_packages===null)
			return;
		$baseUrl=$this->getCoreScriptUrl();
		$cssFiles=array();
		$jsFiles=array();
		foreach($this->_coreScripts as $name)
		{
			foreach($this->_packages[$name] as $path)
			{
				$url=$baseUrl.'/'.$path;
				if(substr($path,-4)==='.css')
					$cssFiles[$url]='';
				else
					$jsFiles[$url]=$url;
			}
		}
		// merge in place
		if($cssFiles!==array())
		{
			foreach($this->cssFiles as $cssFile=>$media)
				$cssFiles[$cssFile]=$media;
			$this->cssFiles=$cssFiles;
		}
		if($jsFiles!==array())
		{
			if(isset($this->scriptFiles[self::POS_HEAD]))
			{
				foreach($this->scriptFiles[self::POS_HEAD] as $url)
					$jsFiles[$url]=$url;
			}
			$this->scriptFiles[self::POS_HEAD]=$jsFiles;
		}
	}
	public function renderHead(&$output)
	{
		$html='';
		foreach($this->_metas as $meta)
			$html.=CHtml::metaTag($meta['content'],null,null,$meta)."\n";
		foreach($this->_links as $link)
			$html.=CHtml::linkTag(null,null,null,null,$link)."\n";
		foreach($this->cssFiles as $url=>$media)
			$html.=CHtml::cssFile($url,$media)."\n";
		foreach($this->_css as $css)
			$html.=CHtml::css($css[0],$css[1])."\n";
		if($this->enableJavaScript)
		{
			if(isset($this->scriptFiles[self::POS_HEAD]))
			{
				foreach($this->scriptFiles[self::POS_HEAD] as $scriptFile)
					$html.=CHtml::scriptFile($scriptFile)."\n";
			}
			if(isset($this->scripts[self::POS_HEAD]))
				$html.=CHtml::script(implode("\n",$this->scripts[self::POS_HEAD]))."\n";
		}
		if($html!=='')
		{
			$count=0;
			$output=preg_replace('/(<title\b[^>]*>|<\\/head\s*>)/is','<###head###>$1',$output,1,$count);
			if($count)
				$output=str_replace('<###head###>',$html,$output);
			else
				$output=$html.$output;
		}
	}
	public function renderBodyBegin(&$output)
	{
		$html='';
		if(isset($this->scriptFiles[self::POS_BEGIN]))
		{
			foreach($this->scriptFiles[self::POS_BEGIN] as $scriptFile)
				$html.=CHtml::scriptFile($scriptFile)."\n";
		}
		if(isset($this->scripts[self::POS_BEGIN]))
			$html.=CHtml::script(implode("\n",$this->scripts[self::POS_BEGIN]))."\n";
		if($html!=='')
		{
			$count=0;
			$output=preg_replace('/(<body\b[^>]*>)/is','$1<###begin###>',$output,1,$count);
			if($count)
				$output=str_replace('<###begin###>',$html,$output);
			else
				$output=$html.$output;
		}
	}
	public function renderBodyEnd(&$output)
	{
		if(!isset($this->scriptFiles[self::POS_END]) && !isset($this->scripts[self::POS_END])
			&& !isset($this->scripts[self::POS_READY]) && !isset($this->scripts[self::POS_LOAD]))
			return;
		$fullPage=0;
		$output=preg_replace('/(<\\/body\s*>)/is','<###end###>$1',$output,1,$fullPage);
		$html='';
		if(isset($this->scriptFiles[self::POS_END]))
		{
			foreach($this->scriptFiles[self::POS_END] as $scriptFile)
				$html.=CHtml::scriptFile($scriptFile)."\n";
		}
		$scripts=isset($this->scripts[self::POS_END]) ? $this->scripts[self::POS_END] : array();
		if(isset($this->scripts[self::POS_READY]))
		{
			if($fullPage)
				$scripts[]="jQuery(document).ready(function() {\n".implode("\n",$this->scripts[self::POS_READY])."\n});";
			else
				$scripts[]=implode("\n",$this->scripts[self::POS_READY]);
		}
		if(isset($this->scripts[self::POS_LOAD]))
		{
			if($fullPage)
				$scripts[]="window.onload=function() {\n".implode("\n",$this->scripts[self::POS_LOAD])."\n};";
			else
				$scripts[]=implode("\n",$this->scripts[self::POS_LOAD]);
		}
		if(!empty($scripts))
			$html.=CHtml::script(implode("\n",$scripts))."\n";
		if($fullPage)
			$output=str_replace('<###end###>',$html,$output);
		else
			$output=$output.$html;
	}
	public function getCoreScriptUrl()
	{
		if($this->_baseUrl!==null)
			return $this->_baseUrl;
		else
			return $this->_baseUrl=Yii::app()->getAssetManager()->publish(YII_PATH.'/web/js/source');
	}
	public function setCoreScriptUrl($value)
	{
		$this->_baseUrl=$value;
	}
	public function registerCoreScript($name)
	{
		if(isset($this->_coreScripts[$name]))
			return;
		if($this->_packages===null)
		{
			$config=require(YII_PATH.'/web/js/packages.php');
			$this->_packages=$config[0];
			$this->_dependencies=$config[1];
		}
		if(!isset($this->_packages[$name]))
			return;
		if(isset($this->_dependencies[$name]))
		{
			foreach($this->_dependencies[$name] as $depName)
				$this->registerCoreScript($depName);
		}
		$this->_hasScripts=true;
		$this->_coreScripts[$name]=$name;
		$params=func_get_args();
		$this->recordCachingAction('clientScript','registerCoreScript',$params);
	}
	public function registerCssFile($url,$media='')
	{
		$this->_hasScripts=true;
		$this->cssFiles[$url]=$media;
		$params=func_get_args();
		$this->recordCachingAction('clientScript','registerCssFile',$params);
	}
	public function registerCss($id,$css,$media='')
	{
		$this->_hasScripts=true;
		$this->_css[$id]=array($css,$media);
		$params=func_get_args();
		$this->recordCachingAction('clientScript','registerCss',$params);
	}
	public function registerScriptFile($url,$position=self::POS_HEAD)
	{
		$this->_hasScripts=true;
		$this->scriptFiles[$position][$url]=$url;
		$params=func_get_args();
		$this->recordCachingAction('clientScript','registerScriptFile',$params);
	}
	public function registerScript($id,$script,$position=self::POS_READY)
	{
		$this->_hasScripts=true;
		$this->scripts[$position][$id]=$script;
		if($position===self::POS_READY)
			$this->registerCoreScript('jquery');
		$params=func_get_args();
		$this->recordCachingAction('clientScript','registerScript',$params);
	}
	public function registerMetaTag($content,$name=null,$httpEquiv=null,$options=array())
	{
		$this->_hasScripts=true;
		$options['content']=$content;
		if($name!==null)
			$options['name']=$name;
		if($httpEquiv!==null)
			$options['http-equiv']=$httpEquiv;
		$this->_metas[serialize($options)]=$options;
		$params=func_get_args();
		$this->recordCachingAction('clientScript','registerMetaTag',$params);
	}
	public function registerLinkTag($relation=null,$type=null,$href=null,$media=null,$options=array())
	{
		$this->_hasScripts=true;
		if($relation!==null)
			$options['rel']=$relation;
		if($type!==null)
			$options['type']=$type;
		if($href!==null)
			$options['href']=$href;
		if($media!==null)
			$options['media']=$media;
		$this->_links[serialize($options)]=$options;
		$params=func_get_args();
		$this->recordCachingAction('clientScript','registerLinkTag',$params);
	}
	public function isCssFileRegistered($url)
	{
		return isset($this->cssFiles[$url]);
	}
	public function isCssRegistered($id)
	{
		return isset($this->_css[$id]);
	}
	public function isScriptFileRegistered($url,$position=self::POS_HEAD)
	{
		return isset($this->scriptFiles[$position][$url]);
	}
	public function isScriptRegistered($id,$position=self::POS_READY)
	{
		return isset($this->scripts[$position][$id]);
	}
	protected function recordCachingAction($context,$method,$params)
	{
		if(($controller=Yii::app()->getController())!==null)
			$controller->recordCachingAction($context,$method,$params);
	}
}
class CList extends CComponent implements IteratorAggregate,ArrayAccess,Countable
{
	private $_d=array();
	private $_c=0;
	private $_r=false;
	public function __construct($data=null,$readOnly=false)
	{
		if($data!==null)
			$this->copyFrom($data);
		$this->setReadOnly($readOnly);
	}
	public function getReadOnly()
	{
		return $this->_r;
	}
	protected function setReadOnly($value)
	{
		$this->_r=$value;
	}
	public function getIterator()
	{
		return new CListIterator($this->_d);
	}
	public function count()
	{
		return $this->getCount();
	}
	public function getCount()
	{
		return $this->_c;
	}
	public function itemAt($index)
	{
		if(isset($this->_d[$index]))
			return $this->_d[$index];
		else if($index>=0 && $index<$this->_c) // in case the value is null
			return $this->_d[$index];
		else
			throw new CException(Yii::t('yii','List index "{index}" is out of bound.',
				array('{index}'=>$index)));
	}
	public function add($item)
	{
		$this->insertAt($this->_c,$item);
		return $this->_c-1;
	}
	public function insertAt($index,$item)
	{
		if(!$this->_r)
		{
			if($index===$this->_c)
				$this->_d[$this->_c++]=$item;
			else if($index>=0 && $index<$this->_c)
			{
				array_splice($this->_d,$index,0,array($item));
				$this->_c++;
			}
			else
				throw new CException(Yii::t('yii','List index "{index}" is out of bound.',
					array('{index}'=>$index)));
		}
		else
			throw new CException(Yii::t('yii','The list is read only.'));
	}
	public function remove($item)
	{
		if(($index=$this->indexOf($item))>=0)
		{
			$this->removeAt($index);
			return $index;
		}
		else
			return false;
	}
	public function removeAt($index)
	{
		if(!$this->_r)
		{
			if($index>=0 && $index<$this->_c)
			{
				$this->_c--;
				if($index===$this->_c)
					return array_pop($this->_d);
				else
				{
					$item=$this->_d[$index];
					array_splice($this->_d,$index,1);
					return $item;
				}
			}
			else
				throw new CException(Yii::t('yii','List index "{index}" is out of bound.',
					array('{index}'=>$index)));
		}
		else
			throw new CException(Yii::t('yii','The list is read only.'));
	}
	public function clear()
	{
		for($i=$this->_c-1;$i>=0;--$i)
			$this->removeAt($i);
	}
	public function contains($item)
	{
		return $this->indexOf($item)>=0;
	}
	public function indexOf($item)
	{
		if(($index=array_search($item,$this->_d,true))!==false)
			return $index;
		else
			return -1;
	}
	public function toArray()
	{
		return $this->_d;
	}
	public function copyFrom($data)
	{
		if(is_array($data) || ($data instanceof Traversable))
		{
			if($this->_c>0)
				$this->clear();
			if($data instanceof CList)
				$data=$data->_d;
			foreach($data as $item)
				$this->add($item);
		}
		else if($data!==null)
			throw new CException(Yii::t('yii','List data must be an array or an object implementing Traversable.'));
	}
	public function mergeWith($data)
	{
		if(is_array($data) || ($data instanceof Traversable))
		{
			if($data instanceof CList)
				$data=$data->_d;
			foreach($data as $item)
				$this->add($item);
		}
		else if($data!==null)
			throw new CException(Yii::t('yii','List data must be an array or an object implementing Traversable.'));
	}
	public function offsetExists($offset)
	{
		return ($offset>=0 && $offset<$this->_c);
	}
	public function offsetGet($offset)
	{
		return $this->itemAt($offset);
	}
	public function offsetSet($offset,$item)
	{
		if($offset===null || $offset===$this->_c)
			$this->insertAt($this->_c,$item);
		else
		{
			$this->removeAt($offset);
			$this->insertAt($offset,$item);
		}
	}
	public function offsetUnset($offset)
	{
		$this->removeAt($offset);
	}
}
class CFilterChain extends CList
{
	public $controller;
	public $action;
	public $filterIndex=0;
	public function __construct($controller,$action)
	{
		$this->controller=$controller;
		$this->action=$action;
	}
	public static function create($controller,$action,$filters)
	{
		$chain=new CFilterChain($controller,$action);
		$actionID=$action->getId();
		foreach($filters as $filter)
		{
			if(is_string($filter))  // filterName [+|- action1 action2]
			{
				if(($pos=strpos($filter,'+'))!==false || ($pos=strpos($filter,'-'))!==false)
				{
					$matched=preg_match("/\b{$actionID}\b/i",substr($filter,$pos+1))>0;
					if(($filter[$pos]==='+')===$matched)
						$chain->add(CInlineFilter::create($controller,trim(substr($filter,0,$pos))));
				}
				else
					$chain->add(CInlineFilter::create($controller,$filter));
			}
			else if(is_array($filter))  // array('path.to.class [+|- action1, action2]','param1'=>'value1',...)
			{
				if(!isset($filter[0]))
					throw new CException(Yii::t('yii','The first element in a filter configuration must be the filter class.'));
				$filterClass=$filter[0];
				unset($filter[0]);
				if(($pos=strpos($filterClass,'+'))!==false || ($pos=strpos($filterClass,'-'))!==false)
				{
					$matched=preg_match("/\b{$actionID}\b/i",substr($filterClass,$pos+1))>0;
					if(($filterClass[$pos]==='+')===$matched)
						$filterClass=trim(substr($filterClass,0,$pos));
					else
						continue;
				}
				$filter['class']=$filterClass;
				$chain->add(Yii::createComponent($filter));
			}
			else
				$chain->add($filter);
		}
		return $chain;
	}
	public function insertAt($index,$item)
	{
		if($item instanceof IFilter)
			parent::insertAt($index,$item);
		else
			throw new CException(Yii::t('yii','CFilterChain can only take objects implementing the IFilter interface.'));
	}
	public function run()
	{
		if($this->offsetExists($this->filterIndex))
		{
			$filter=$this->itemAt($this->filterIndex++);
			$filter->filter($this);
		}
		else
			$this->controller->runAction($this->action);
	}
}
class CFilter extends CComponent implements IFilter
{
	public function filter($filterChain)
	{
		if($this->preFilter($filterChain))
		{
			$filterChain->run();
			$this->postFilter($filterChain);
		}
	}
	protected function preFilter($filterChain)
	{
		return true;
	}
	protected function postFilter($filterChain)
	{
	}
}
class CInlineFilter extends CFilter
{
	public $name;
	public static function create($controller,$filterName)
	{
		if(method_exists($controller,'filter'.$filterName))
		{
			$filter=new CInlineFilter;
			$filter->name=$filterName;
			return $filter;
		}
		else
			throw new CException(Yii::t('yii','Filter "{filter}" is invalid. Controller "{class}" does have the filter method "filter{filter}".',
				array('{filter}'=>$filterName, '{class}'=>get_class($controller))));
	}
	public function filter($filterChain)
	{
		$method='filter'.$this->name;
		$filterChain->controller->$method($filterChain);
	}
}
class CAccessControlFilter extends CFilter
{
	private $_rules=array();
	public function getRules()
	{
		return $this->_rules;
	}
	public function setRules($rules)
	{
		foreach($rules as $rule)
		{
			if(is_array($rule) && isset($rule[0]))
			{
				$r=new CAccessRule;
				$r->allow=$rule[0]==='allow';
				foreach(array_slice($rule,1) as $name=>$value)
				{
					if($name==='expression' || $name==='roles')
						$r->$name=$value;
					else
						$r->$name=array_map('strtolower',$value);
				}
				$this->_rules[]=$r;
			}
		}
	}
	protected function preFilter($filterChain)
	{
		$app=Yii::app();
		$request=$app->getRequest();
		$user=$app->getUser();
		$verb=$request->getRequestType();
		$ip=$request->getUserHostAddress();
		foreach($this->getRules() as $rule)
		{
			if(($allow=$rule->isUserAllowed($user,$filterChain->controller,$filterChain->action,$ip,$verb))>0) // allowed
				break;
			else if($allow<0) // denied
			{
				$this->accessDenied($user);
				return false;
			}
		}
		return true;
	}
	protected function accessDenied($user)
	{
		if($user->getIsGuest())
			$user->loginRequired();
		else
			throw new CHttpException(403,Yii::t('yii','You are not authorized to perform this action.'));
	}
}
class CAccessRule extends CComponent
{
	public $allow;
	public $actions;
	public $controllers;
	public $users;
	public $roles;
	public $ips;
	public $verbs;
	public $expression;
	public function isUserAllowed($user,$controller,$action,$ip,$verb)
	{
		if($this->isActionMatched($action)
			&& $this->isUserMatched($user)
			&& $this->isRoleMatched($user)
			&& $this->isIpMatched($ip)
			&& $this->isVerbMatched($verb)
			&& $this->isControllerMatched($controller)
			&& $this->isExpressionMatched($user))
			return $this->allow ? 1 : -1;
		else
			return 0;
	}
	protected function isActionMatched($action)
	{
		return empty($this->actions) || in_array(strtolower($action->getId()),$this->actions);
	}
	protected function isControllerMatched($controller)
	{
		return empty($this->controllers) || in_array(strtolower($controller->getId()),$this->controllers);
	}
	protected function isUserMatched($user)
	{
		if(empty($this->users))
			return true;
		foreach($this->users as $u)
		{
			if($u==='*')
				return true;
			else if($u==='?' && $user->getIsGuest())
				return true;
			else if($u==='@' && !$user->getIsGuest())
				return true;
			else if(!strcasecmp($u,$user->getName()))
				return true;
		}
		return false;
	}
	protected function isRoleMatched($user)
	{
		if(empty($this->roles))
			return true;
		foreach($this->roles as $role)
		{
			if($user->checkAccess($role))
				return true;
		}
		return false;
	}
	protected function isIpMatched($ip)
	{
		if(empty($this->ips))
			return true;
		foreach($this->ips as $rule)
		{
			if($rule==='*' || $rule===$ip || (($pos=strpos($rule,'*'))!==false && !strncmp($ip,$rule,$pos)))
				return true;
		}
		return false;
	}
	protected function isVerbMatched($verb)
	{
		return empty($this->verbs) || in_array(strtolower($verb),$this->verbs);
	}
	protected function isExpressionMatched($user)
	{
		if($this->expression===null)
			return true;
		if(!is_string($this->expression) && is_callable($this->expression))
			return call_user_func($this->expression, $user);
		else
			return @eval('return '.$this->expression.';');
	}
}
abstract class CModel extends CComponent implements IteratorAggregate, ArrayAccess
{
	private $_errors=array();	// attribute name => array of errors
	private $_va;  // validator
	private $_se='';  // scenario
	abstract public function attributeNames();
	abstract public function safeAttributes();
	public function rules()
	{
		return array();
	}
	public function behaviors()
	{
		return array();
	}
	public function attributeLabels()
	{
		return array();
	}
	public function validate($scenario='',$attributes=null)
	{
		if($scenario==='')
			$scenario=$this->getScenario();
		$this->clearErrors();
		if($this->beforeValidate($scenario))
		{
			foreach($this->getValidators() as $validator)
			{
				if($validator->applyTo($scenario))
					$validator->validate($this,$attributes);
			}
			$this->afterValidate($scenario);
			return !$this->hasErrors();
		}
		else
			return false;
	}
	protected function beforeValidate($scenario)
	{
		$event=new CModelEvent($this);
		$this->onBeforeValidate($event);
		return $event->isValid;
	}
	protected function afterValidate($scenario)
	{
		$this->onAfterValidate(new CEvent($this));
	}
	public function onBeforeValidate($event)
	{
		$this->raiseEvent('onBeforeValidate',$event);
	}
	public function onAfterValidate($event)
	{
		$this->raiseEvent('onAfterValidate',$event);
	}
	public function getValidators()
	{
		return $this->createValidators();
	}
	public function getValidatorsForAttribute($attribute,$scenario='')
	{
		if($scenario==='')
			$scenario=$this->getScenario();
		if($this->_va===null)
		{
			$this->_va=array();
			foreach($this->getValidators() as $validator)
			{
				foreach($validator->attributes as $att)
					$this->_va[$att][]=$validator;
			}
		}
		$validators=array();
		if(isset($this->_va[$attribute]))
		{
			foreach($this->_va[$attribute] as $validator)
			{
				if($validator->applyTo($scenario))
					$validators[]=$validator;
			}
		}
		return $validators;
	}
	public function isAttributeRequired($attribute,$scenario='')
	{
		$validators=$this->getValidatorsForAttribute($attribute,$scenario);
		foreach($validators as $validator)
		{
			if($validator instanceof CRequiredValidator)
				return true;
		}
		return false;
	}
	public function getAttributeLabel($attribute)
	{
		$labels=$this->attributeLabels();
		if(isset($labels[$attribute]))
			return $labels[$attribute];
		else
			return $this->generateAttributeLabel($attribute);
	}
	public function hasErrors($attribute=null)
	{
		if($attribute===null)
			return $this->_errors!==array();
		else
			return isset($this->_errors[$attribute]);
	}
	public function getErrors($attribute=null)
	{
		if($attribute===null)
			return $this->_errors;
		else
			return isset($this->_errors[$attribute]) ? $this->_errors[$attribute] : array();
	}
	public function getError($attribute)
	{
		return isset($this->_errors[$attribute]) ? reset($this->_errors[$attribute]) : null;
	}
	public function addError($attribute,$error)
	{
		$this->_errors[$attribute][]=$error;
	}
	public function addErrors($errors)
	{
		foreach($errors as $attribute=>$error)
		{
			if(is_array($error))
			{
				foreach($error as $e)
					$this->_errors[$attribute][]=$e;
			}
			else
				$this->_errors[$attribute][]=$error;
		}
	}
	public function clearErrors($attribute=null)
	{
		if($attribute===null)
			$this->_errors=array();
		else
			unset($this->_errors[$attribute]);
	}
	public function createValidators()
	{
		$validators=array();
		foreach($this->rules() as $rule)
		{
			if(isset($rule[0],$rule[1]))  // attributes, validator name
				$validators[]=CValidator::createValidator($rule[1],$this,$rule[0],array_slice($rule,2));
			else
				throw new CException(Yii::t('yii','{class} has an invalid validation rule. The rule must specify attributes to be validated and the validator name.',
					array('{class}'=>get_class($this))));
		}
		return $validators;
	}
	public function generateAttributeLabel($name)
	{
		return ucwords(trim(strtolower(str_replace(array('-','_'),' ',preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $name)))));
	}
	public function getAttributes($names=null)
	{
		$values=array();
		foreach($this->attributeNames() as $name)
			$values[$name]=$this->$name;
		if(is_array($names))
		{
			$values2=array();
			foreach($names as $name)
				$values2[$name]=isset($values[$name]) ? $values[$name] : null;
			return $values2;
		}
		else
			return $values;
	}
	public function setAttributes($values,$scenario='')
	{
		if($scenario==='')
			$scenario=$this->getScenario();
		if(is_array($values))
		{
			$attributes=array_flip($this->getSafeAttributeNames($scenario));
			foreach($values as $name=>$value)
			{
				if(isset($attributes[$name]))
					$this->$name=$value;
			}
		}
	}
	public function getScenario()
	{
		return $this->_se;
	}
	public function setScenario($value)
	{
		$this->_se=$value;
	}
	public function getSafeAttributeNames($scenario='')
	{
		if($scenario==='')
			$scenario=$this->getScenario();
		if($scenario===false)
			return $this->attributeNames();
		$attributes=$this->safeAttributes();
		if(!is_array($attributes))
			$attributes=array($attributes);
		if($scenario!=='' && isset($attributes[$scenario]))
			return $this->ensureArray($attributes[$scenario]);
		if(isset($attributes[0], $attributes[1]))
			return $attributes;
		else
			return isset($attributes[0]) ? $this->ensureArray($attributes[0]) : array();
	}
	public function getIterator()
	{
		$attributes=$this->getAttributes();
		return new CMapIterator($attributes);
	}
	public function offsetExists($offset)
	{
		return property_exists($this,$offset);
	}
	public function offsetGet($offset)
	{
		return $this->$offset;
	}
	public function offsetSet($offset,$item)
	{
		$this->$offset=$item;
	}
	public function offsetUnset($offset)
	{
		unset($this->$offset);
	}
	private function ensureArray($value)
	{
		return is_array($value) ? $value : preg_split('/[\s,]+/',$value,-1,PREG_SPLIT_NO_EMPTY);
	}
}
abstract class CActiveRecord extends CModel
{
	const BELONGS_TO='CBelongsToRelation';
	const HAS_ONE='CHasOneRelation';
	const HAS_MANY='CHasManyRelation';
	const MANY_MANY='CManyManyRelation';
	const STAT='CStatRelation';
	public static $db;
	private static $_models=array();			// class name => model
	private $_md;								// meta data
	private $_new=false;						// whether this instance is new or not
	private $_attributes=array();				// attribute name => attribute value
	private $_related=array();					// attribute name => related objects
	private $_c;								// query criteria (used by finder only)
	public function __construct($attributes=array(),$scenario='')
	{
		if($attributes===null) // internally used by populateRecord() and model()
			return;
		$this->setScenario($scenario);
		$this->setIsNewRecord(true);
		$this->_attributes=$this->getMetaData()->attributeDefaults;
		$this->init();
		if($attributes!==array())
			$this->setAttributes($attributes);
		$this->attachBehaviors($this->behaviors());
		$this->afterConstruct();
	}
	public function init()
	{
	}
	public function __sleep()
	{
		$this->_md=null;
		return array_keys((array)$this);
	}
	public function __get($name)
	{
		if(isset($this->_attributes[$name]))
			return $this->_attributes[$name];
		else if(isset($this->getMetaData()->columns[$name]))
			return null;
		else if(isset($this->_related[$name]))
			return $this->_related[$name];
		else if(isset($this->getMetaData()->relations[$name]))
			return $this->getRelated($name);
		else
			return parent::__get($name);
	}
	public function __set($name,$value)
	{
		if($this->setAttribute($name,$value)===false)
		{
			if(isset($this->getMetaData()->relations[$name]))
				$this->_related[$name]=$value;
			else
				parent::__set($name,$value);
		}
	}
	public function __isset($name)
	{
		if(isset($this->_attributes[$name]))
			return true;
		else if(isset($this->getMetaData()->columns[$name]))
			return false;
		else if(isset($this->_related[$name]))
			return true;
		else if(isset($this->getMetaData()->relations[$name]))
			return $this->getRelated($name)!==null;
		else
			return parent::__isset($name);
	}
	public function __unset($name)
	{
		if(isset($this->getMetaData()->columns[$name]))
			unset($this->_attributes[$name]);
		else if(isset($this->getMetaData()->relations[$name]))
			unset($this->_related[$name]);
		else
			parent::__unset($name);
	}
	public function __call($name,$parameters)
	{
		if(isset($this->getMetaData()->relations[$name]))
		{
			if(empty($parameters))
				return $this->getRelated($name,false);
			else
				return $this->getRelated($name,false,$parameters[0]);
		}
		$scopes=$this->scopes();
		if(isset($scopes[$name]))
		{
			$this->getDbCriteria()->mergeWith($scopes[$name]);
			return $this;
		}
		return parent::__call($name,$parameters);
	}
	public function getRelated($name,$refresh=false,$params=array())
	{
		if(!$refresh && $params===array() && (isset($this->_related[$name]) || array_key_exists($name,$this->_related)))
			return $this->_related[$name];
		$md=$this->getMetaData();
		if(!isset($md->relations[$name]))
			throw new CDbException(Yii::t('yii','{class} does not have relation "{name}".',
				array('{class}'=>get_class($this), '{name}'=>$name)));
		$relation=$md->relations[$name];
		if($this->getIsNewRecord() && ($relation instanceof CHasOneRelation || $relation instanceof CHasManyRelation))
			return $relation instanceof CHasOneRelation ? null : array();
		if($params!==array()) // dynamic query
		{
			$exists=isset($this->_related[$name]) || array_key_exists($name,$this->_related);
			if($exists)
				$save=$this->_related[$name];
			unset($this->_related[$name]);
			$r=array($name=>$params);
		}
		else
			$r=$name;
		$finder=new CActiveFinder($this,$r);
		$finder->lazyFind($this);
		if(!isset($this->_related[$name]))
		{
			if($relation instanceof CHasManyRelation)
				$this->_related[$name]=array();
			else if($relation instanceof CStatRelation)
				$this->_related[$name]=$relation->defaultValue;
			else
				$this->_related[$name]=null;
		}
		if($params!==array())
		{
			$results=$this->_related[$name];
			if($exists)
				$this->_related[$name]=$save;
			else
				unset($this->_related[$name]);
			return $results;
		}
		else
			return $this->_related[$name];
	}
	public function hasRelated($name)
	{
		return isset($this->_related[$name]) || array_key_exists($name,$this->_related);
	}
	public function getDbCriteria($createIfNull=true)
	{
		if($this->_c===null)
		{
			if(($c=$this->defaultScope())!==array() || $createIfNull)
				$this->_c=new CDbCriteria($c);
		}
		return $this->_c;
	}
	public function defaultScope()
	{
		return array();
	}
	public static function model($className=__CLASS__)
	{
		if(isset(self::$_models[$className]))
			return self::$_models[$className];
		else
		{
			$model=self::$_models[$className]=new $className(null);
			$model->attachBehaviors($model->behaviors());
			$model->_md=new CActiveRecordMetaData($model);
			return $model;
		}
	}
	public function getMetaData()
	{
		if($this->_md!==null)
			return $this->_md;
		else
			return $this->_md=self::model(get_class($this))->_md;
	}
	public function refreshMetaData()
	{
		$finder=self::model(get_class($this));
		$finder->_md=new CActiveRecordMetaData($finder);
		if($this!==$finder)
			$this->_md=$finder->_md;
	}
	public function tableName()
	{
		return get_class($this);
	}
	public function primaryKey()
	{
	}
	public function relations()
	{
		return array();
	}
	public function scopes()
	{
		return array();
	}
	public function attributeNames()
	{
		return array_keys($this->getMetaData()->columns);
	}
	public function safeAttributes()
	{
		$attributes=array();
		foreach($this->getMetaData()->columns as $name=>$column)
		{
			if(!$column->isPrimaryKey)
				$attributes[]=$name;
		}
		return $attributes;
	}
	public function getDbConnection()
	{
		if(self::$db!==null)
			return self::$db;
		else
		{
			self::$db=Yii::app()->getDb();
			if(self::$db instanceof CDbConnection)
			{
				self::$db->setActive(true);
				return self::$db;
			}
			else
				throw new CDbException(Yii::t('yii','Active Record requires a "db" CDbConnection application component.'));
		}
	}
	public function getActiveRelation($name)
	{
		return isset($this->getMetaData()->relations[$name]) ? $this->getMetaData()->relations[$name] : null;
	}
	public function getTableSchema()
	{
		return $this->getMetaData()->tableSchema;
	}
	public function getCommandBuilder()
	{
		return $this->getDbConnection()->getSchema()->getCommandBuilder();
	}
	public function hasAttribute($name)
	{
		return isset($this->getMetaData()->columns[$name]);
	}
	public function getAttribute($name)
	{
		if(property_exists($this,$name))
			return $this->$name;
		else if(isset($this->_attributes[$name]))
			return $this->_attributes[$name];
	}
	public function setAttribute($name,$value)
	{
		if(property_exists($this,$name))
			$this->$name=$value;
		else if(isset($this->getMetaData()->columns[$name]))
			$this->_attributes[$name]=$value;
		else
			return false;
		return true;
	}
	public function addRelatedRecord($name,$record,$index)
	{
		if($index!==false)
		{
			if(!isset($this->_related[$name]))
				$this->_related[$name]=array();
			if($record instanceof CActiveRecord)
			{
				if($index===true)
					$this->_related[$name][]=$record;
				else
					$this->_related[$name][$index]=$record;
			}
		}
		else if(!isset($this->_related[$name]))
			$this->_related[$name]=$record;
	}
	public function getAttributes($names=true)
	{
		$attributes=$this->_attributes;
		foreach($this->getMetaData()->columns as $name=>$column)
		{
			if(property_exists($this,$name))
				$attributes[$name]=$this->$name;
			else if($names===true && !isset($attributes[$name]))
				$attributes[$name]=null;
		}
		if(is_array($names))
		{
			$attrs=array();
			foreach($names as $name)
				$attrs[$name]=isset($attributes[$name])?$attributes[$name]:null;
			return $attrs;
		}
		else
			return $attributes;
	}
	public function save($runValidation=true,$attributes=null)
	{
		if(($scenario=$this->getScenario())==='')
			$scenario=$this->getIsNewRecord()?'insert':'update';
		if(!$runValidation || $this->validate($scenario,$attributes))
			return $this->getIsNewRecord() ? $this->insert($attributes) : $this->update($attributes);
		else
			return false;
	}
	public function getIsNewRecord()
	{
		return $this->_new;
	}
	public function setIsNewRecord($value)
	{
		$this->_new=$value;
		if(!$value && $this->getScenario()==='insert')
			$this->setScenario('update');
	}
	public function getValidators()
	{
		return $this->getMetaData()->getValidators();
	}
	public function onBeforeSave($event)
	{
		$this->raiseEvent('onBeforeSave',$event);
	}
	public function onAfterSave($event)
	{
		$this->raiseEvent('onAfterSave',$event);
	}
	public function onBeforeDelete($event)
	{
		$this->raiseEvent('onBeforeDelete',$event);
	}
	public function onAfterDelete($event)
	{
		$this->raiseEvent('onAfterDelete',$event);
	}
	public function onAfterConstruct($event)
	{
		$this->raiseEvent('onAfterConstruct',$event);
	}
	public function onBeforeFind($event)
	{
		$this->raiseEvent('onBeforeFind',$event);
	}
	public function onAfterFind($event)
	{
		$this->raiseEvent('onAfterFind',$event);
	}
	protected function beforeSave()
	{
		if($this->hasEventHandler('onBeforeSave'))
		{
			$event=new CModelEvent($this);
			$this->onBeforeSave($event);
			return $event->isValid;
		}
		else
			return true;
	}
	protected function afterSave()
	{
		if($this->hasEventHandler('onAfterSave'))
			$this->onAfterSave(new CEvent($this));
	}
	protected function beforeDelete()
	{
		if($this->hasEventHandler('onBeforeDelete'))
		{
			$event=new CModelEvent($this);
			$this->onBeforeDelete($event);
			return $event->isValid;
		}
		else
			return true;
	}
	protected function afterDelete()
	{
		if($this->hasEventHandler('onAfterDelete'))
			$this->onAfterDelete(new CEvent($this));
	}
	protected function afterConstruct()
	{
		if($this->hasEventHandler('onAfterConstruct'))
			$this->onAfterConstruct(new CEvent($this));
	}
	protected function beforeFind()
	{
		if($this->hasEventHandler('onBeforeFind'))
			$this->onBeforeFind(new CEvent($this));
	}
	protected function afterFind()
	{
		if($this->hasEventHandler('onAfterFind'))
			$this->onAfterFind(new CEvent($this));
	}
	public function beforeFindInternal()
	{
		$this->beforeFind();
	}
	public function afterFindInternal()
	{
		$this->afterFind();
	}
	public function insert($attributes=null)
	{
		if(!$this->getIsNewRecord())
			throw new CDbException(Yii::t('yii','The active record cannot be inserted to database because it is not new.'));
		if($this->beforeSave())
		{
			$builder=$this->getCommandBuilder();
			$table=$this->getMetaData()->tableSchema;
			$command=$builder->createInsertCommand($table,$this->getAttributes($attributes));
			if($command->execute())
			{
				$primaryKey=$table->primaryKey;
				if($table->sequenceName!==null)
				{
					if(is_string($primaryKey) && $this->$primaryKey===null)
						$this->$primaryKey=$builder->getLastInsertID($table);
					else if(is_array($primaryKey))
					{
						foreach($primaryKey as $pk)
						{
							if($this->$pk===null)
							{
								$this->$pk=$builder->getLastInsertID($table);
								break;
							}
						}
					}
				}
				$this->afterSave();
				$this->setIsNewRecord(false);
				return true;
			}
			else
				$this->afterSave();
		}
		else
			return false;
	}
	public function update($attributes=null)
	{
		if($this->getIsNewRecord())
			throw new CDbException(Yii::t('yii','The active record cannot be updated because it is new.'));
		if($this->beforeSave())
		{
			$this->updateByPk($this->getPrimaryKey(),$this->getAttributes($attributes));
			$this->afterSave();
			return true;
		}
		else
			return false;
	}
	public function saveAttributes($attributes)
	{
		if(!$this->getIsNewRecord())
		{
			$values=array();
			foreach($attributes as $name=>$value)
			{
				if(is_integer($name))
					$values[$value]=$this->$value;
				else
					$values[$name]=$this->$name=$value;
			}
			return $this->updateByPk($this->getPrimaryKey(),$values)>0;
		}
		else
			throw new CDbException(Yii::t('yii','The active record cannot be updated because it is new.'));
	}
	public function delete()
	{
		if(!$this->getIsNewRecord())
		{
			if($this->beforeDelete())
			{
				$result=$this->deleteByPk($this->getPrimaryKey())>0;
				$this->afterDelete();
				return $result;
			}
			else
				return false;
		}
		else
			throw new CDbException(Yii::t('yii','The active record cannot be deleted because it is new.'));
	}
	public function refresh()
	{
		if(!$this->getIsNewRecord() && ($record=$this->findByPk($this->getPrimaryKey()))!==null)
		{
			$this->_attributes=array();
			$this->_related=array();
			foreach($this->getMetaData()->columns as $name=>$column)
				$this->$name=$record->$name;
			return true;
		}
		else
			return false;
	}
	public function equals($record)
	{
		return $this->tableName()===$record->tableName() && $this->getPrimaryKey()===$record->getPrimaryKey();
	}
	public function getPrimaryKey()
	{
		$table=$this->getMetaData()->tableSchema;
		if(is_string($table->primaryKey))
			return $this->{$table->primaryKey};
		else if(is_array($table->primaryKey))
		{
			$values=array();
			foreach($table->primaryKey as $name)
				$values[$name]=$this->$name;
			return $values;
		}
		else
			return null;
	}
	private function query($criteria,$all=false)
	{
		$this->beforeFind();
		$this->applyScopes($criteria);
		$command=$this->getCommandBuilder()->createFindCommand($this->getTableSchema(),$criteria);
		return $all ? $this->populateRecords($command->queryAll()) : $this->populateRecord($command->queryRow());
	}
	private function applyScopes(&$criteria)
	{
		if(($c=$this->getDbCriteria(false))!==null)
		{
			$c->mergeWith($criteria);
			$criteria=$c;
			$this->_c=null;
		}
	}
	public function find($condition='',$params=array())
	{
		$criteria=$this->getCommandBuilder()->createCriteria($condition,$params);
		$criteria->limit=1;
		return $this->query($criteria);
	}
	public function findAll($condition='',$params=array())
	{
		$criteria=$this->getCommandBuilder()->createCriteria($condition,$params);
		return $this->query($criteria,true);
	}
	public function findByPk($pk,$condition='',$params=array())
	{
		$criteria=$this->getCommandBuilder()->createPkCriteria($this->getTableSchema(),$pk,$condition,$params);
		$criteria->limit=1;
		return $this->query($criteria);
	}
	public function findAllByPk($pk,$condition='',$params=array())
	{
		$criteria=$this->getCommandBuilder()->createPkCriteria($this->getTableSchema(),$pk,$condition,$params);
		return $this->query($criteria,true);
	}
	public function findByAttributes($attributes,$condition='',$params=array())
	{
		$criteria=$this->getCommandBuilder()->createColumnCriteria($this->getTableSchema(),$attributes,$condition,$params);
		$criteria->limit=1;
		return $this->query($criteria);
	}
	public function findAllByAttributes($attributes,$condition='',$params=array())
	{
		$criteria=$this->getCommandBuilder()->createColumnCriteria($this->getTableSchema(),$attributes,$condition,$params);
		return $this->query($criteria,true);
	}
	public function findBySql($sql,$params=array())
	{
		$command=$this->getCommandBuilder()->createSqlCommand($sql,$params);
		return $this->populateRecord($command->queryRow());
	}
	public function findAllBySql($sql,$params=array())
	{
		$command=$this->getCommandBuilder()->createSqlCommand($sql,$params);
		return $this->populateRecords($command->queryAll());
	}
	public function count($condition='',$params=array())
	{
		$builder=$this->getCommandBuilder();
		$criteria=$builder->createCriteria($condition,$params);
		$this->applyScopes($criteria);
		return $builder->createCountCommand($this->getTableSchema(),$criteria)->queryScalar();
	}
	public function countBySql($sql,$params=array())
	{
		return $this->getCommandBuilder()->createSqlCommand($sql,$params)->queryScalar();
	}
	public function exists($condition,$params=array())
	{
		$builder=$this->getCommandBuilder();
		$criteria=$builder->createCriteria($condition,$params);
		$table=$this->getTableSchema();
		$criteria->select=reset($table->columns)->rawName;
		$criteria->limit=1;
		$this->applyScopes($criteria);
		return $builder->createFindCommand($table,$criteria)->queryRow()!==false;
	}
	public function with()
	{
		if(func_num_args()>0)
		{
			$with=func_get_args();
			if(is_array($with[0]))  // the parameter is given as an array
				$with=$with[0];
			$finder=new CActiveFinder($this,$with,$this->getDbCriteria(false));
			$this->_c=null;
			return $finder;
		}
		else
			return $this;
	}
	public function updateByPk($pk,$attributes,$condition='',$params=array())
	{
		$builder=$this->getCommandBuilder();
		$table=$this->getTableSchema();
		$criteria=$builder->createPkCriteria($table,$pk,$condition,$params);
		$command=$builder->createUpdateCommand($table,$attributes,$criteria);
		return $command->execute();
	}
	public function updateAll($attributes,$condition='',$params=array())
	{
		$builder=$this->getCommandBuilder();
		$criteria=$builder->createCriteria($condition,$params);
		$command=$builder->createUpdateCommand($this->getTableSchema(),$attributes,$criteria);
		return $command->execute();
	}
	public function updateCounters($counters,$condition='',$params=array())
	{
		$builder=$this->getCommandBuilder();
		$criteria=$builder->createCriteria($condition,$params);
		$command=$builder->createUpdateCounterCommand($this->getTableSchema(),$counters,$criteria);
		return $command->execute();
	}
	public function deleteByPk($pk,$condition='',$params=array())
	{
		$builder=$this->getCommandBuilder();
		$criteria=$builder->createPkCriteria($this->getTableSchema(),$pk,$condition,$params);
		$command=$builder->createDeleteCommand($this->getTableSchema(),$criteria);
		return $command->execute();
	}
	public function deleteAll($condition='',$params=array())
	{
		$builder=$this->getCommandBuilder();
		$criteria=$builder->createCriteria($condition,$params);
		$command=$builder->createDeleteCommand($this->getTableSchema(),$criteria);
		return $command->execute();
	}
	public function deleteAllByAttributes($attributes,$condition='',$params=array())
	{
		$builder=$this->getCommandBuilder();
		$table=$this->getTableSchema();
		$criteria=$builder->createColumnCriteria($table,$attributes,$condition,$params);
		$command=$builder->createDeleteCommand($table,$criteria);
		return $command->execute();
	}
	public function populateRecord($attributes,$callAfterFind=true)
	{
		if($attributes!==false)
		{
			$record=$this->instantiate($attributes);
			$md=$record->getMetaData();
			foreach($attributes as $name=>$value)
			{
				if(property_exists($record,$name))
					$record->$name=$value;
				else if(isset($md->columns[$name]))
					$record->_attributes[$name]=$value;
			}
			$record->attachBehaviors($record->behaviors());
			if($callAfterFind)
				$record->afterFind();
			return $record;
		}
		else
			return null;
	}
	public function populateRecords($data,$callAfterFind=true)
	{
		$records=array();
		$md=$this->getMetaData();
		foreach($data as $attributes)
		{
			$record=$this->instantiate($attributes);
			$md=$record->getMetaData();
			foreach($attributes as $name=>$value)
			{
				if(property_exists($record,$name))
					$record->$name=$value;
				else if(isset($record->_md->columns[$name]))
					$record->_attributes[$name]=$value;
			}
			$record->attachBehaviors($record->behaviors());
			if($callAfterFind)
				$record->afterFind();
			$records[]=$record;
		}
		return $records;
	}
	protected function instantiate($attributes)
	{
		$class=get_class($this);
		return new $class(null);
	}
	public function offsetExists($offset)
	{
		return isset($this->getMetaData()->columns[$offset]);
	}
}
class CBaseActiveRelation extends CComponent
{
	public $name;
	public $className;
	public $foreignKey;
	public $select='*';
	public $condition='';
	public $params=array();
	public $group='';
	public $having='';
	public $order='';
	public function __construct($name,$className,$foreignKey,$options=array())
	{
		$this->name=$name;
		$this->className=$className;
		$this->foreignKey=$foreignKey;
		foreach($options as $name=>$value)
			$this->$name=$value;
	}
	public function mergeWith($criteria)
	{
		if(isset($criteria['select']) && $this->select!==$criteria['select'])
		{
			if($this->select==='*')
				$this->select=$criteria['select'];
			else if($criteria['select']!=='*')
			{
				$select1=is_string($this->select)?preg_split('/\s*,\s*/',trim($this->select),-1,PREG_SPLIT_NO_EMPTY):$this->select;
				$select2=is_string($criteria['select'])?preg_split('/\s*,\s*/',trim($criteria['select']),-1,PREG_SPLIT_NO_EMPTY):$criteria['select'];
				$this->select=array_merge($select1,array_diff($select2,$select1));
			}
		}
		if(isset($criteria['condition']) && $this->condition!==$criteria['condition'])
		{
			if($this->condition==='')
				$this->condition=$criteria['condition'];
			else if($criteria['condition']!=='')
				$this->condition="({$this->condition}) AND ({$criteria['condition']})";
		}
		if(isset($criteria['params']) && $this->params!==$criteria['params'])
			$this->params=array_merge($this->params,$criteria['params']);
		if(isset($criteria['order']) && $this->order!==$criteria['order'])
		{
			if($this->order==='')
				$this->order=$criteria['order'];
			else if($criteria['order']!=='')
				$this->order.=', '.$criteria['order'];
		}
		if(isset($criteria['group']) && $this->group!==$criteria['group'])
		{
			if($this->group==='')
				$this->group=$criteria['group'];
			else if($criteria['group']!=='')
				$this->group.=', '.$criteria['group'];
		}
		if(isset($criteria['having']) && $this->having!==$criteria['having'])
		{
			if($this->having==='')
				$this->having=$criteria['having'];
			else if($criteria['having']!=='')
				$this->having="({$this->having}) AND ({$criteria['having']})";
		}
	}
}
class CStatRelation extends CBaseActiveRelation
{
	public $select='COUNT(*)';
	public $defaultValue=0;
	public function mergeWith($criteria)
	{
		parent::mergeWith($criteria);
		if(isset($criteria['defaultValue']))
			$this->defaultValue=$criteria['defaultValue'];
	}
}
class CActiveRelation extends CBaseActiveRelation
{
	public $joinType='LEFT OUTER JOIN';
	public $on='';
	public $alias;
	public $aliasToken='??';
	public $with=array();
	public $together;
	public function mergeWith($criteria)
	{
		parent::mergeWith($criteria);
		if(isset($criteria['joinType']))
			$this->joinType=$criteria['joinType'];
		if(isset($criteria['on']) && $this->on!==$criteria['on'])
		{
			if($this->on==='')
				$this->on=$criteria['on'];
			else if($criteria['on']!=='')
				$this->on="({$this->on}) AND ({$criteria['on']})";
		}
		if(isset($criteria['with']))
			$this->with=$criteria['with'];
		if(isset($criteria['alias']))
			$this->alias=$criteria['alias'];
		if(isset($criteria['aliasToken']))
			$this->aliasToken=$criteria['aliasToken'];
		if(isset($criteria['together']))
			$this->together=$criteria['together'];
	}
}
class CBelongsToRelation extends CActiveRelation
{
}
class CHasOneRelation extends CActiveRelation
{
}
class CHasManyRelation extends CActiveRelation
{
	public $limit=-1;
	public $offset=-1;
	public $index;
	public function mergeWith($criteria)
	{
		parent::mergeWith($criteria);
		if(isset($criteria['limit']) && $criteria['limit']>0)
			$this->limit=$criteria['limit'];
		if(isset($criteria['offset']) && $criteria['offset']>=0)
			$this->offset=$criteria['offset'];
		if(isset($criteria['index']))
			$this->index=$criteria['index'];
	}
}
class CManyManyRelation extends CHasManyRelation
{
}
class CActiveRecordMetaData
{
	public $tableSchema;
	public $columns;
	public $relations=array();
	public $attributeDefaults=array();
	private $_model;
	private $_validators;
	public function __construct($model)
	{
		$this->_model=$model;
		$tableName=$model->tableName();
		if(($table=$model->getDbConnection()->getSchema()->getTable($tableName))===null)
			throw new CDbException(Yii::t('yii','The table "{table}" for active record class "{class}" cannot be found in the database.',
				array('{class}'=>get_class($model),'{table}'=>$tableName)));
		if($table->primaryKey===null)
			$table->primaryKey=$model->primaryKey();
		$this->tableSchema=$table;
		$this->columns=$table->columns;
		foreach($table->columns as $name=>$column)
		{
			if(!$column->isPrimaryKey && $column->defaultValue!==null)
				$this->attributeDefaults[$name]=$column->defaultValue;
		}
		foreach($model->relations() as $name=>$config)
		{
			if(isset($config[0],$config[1],$config[2]))  // relation class, AR class, FK
				$this->relations[$name]=new $config[0]($name,$config[1],$config[2],array_slice($config,3));
			else
				throw new CDbException(Yii::t('yii','Active record "{class}" has an invalid configuration for relation "{relation}". It must specify the relation type, the related active record class and the foreign key.',
					array('{class}'=>get_class($model),'{relation}'=>$name)));
		}
	}
	public function getValidators()
	{
		if(!$this->_validators)
			$this->_validators=$this->_model->createValidators();
		return $this->_validators;
	}
}
class CDbConnection extends CApplicationComponent
{
	public $connectionString;
	public $username='';
	public $password='';
	public $schemaCachingDuration=0;
	public $schemaCachingExclude=array();
	public $schemaCacheID='cache';
	public $autoConnect=true;
	public $charset;
	public $emulatePrepare=false;
	public $enableParamLogging=false;
	public $enableProfiling=false;
	private $_attributes=array();
	private $_active=false;
	private $_pdo;
	private $_transaction;
	private $_schema;
	public function __construct($dsn='',$username='',$password='')
	{
		$this->connectionString=$dsn;
		$this->username=$username;
		$this->password=$password;
	}
	public function __sleep()
	{
		$this->close();
		return array_keys(get_object_vars($this));
	}
	public static function getAvailableDrivers()
	{
		return PDO::getAvailableDrivers();
	}
	public function init()
	{
		parent::init();
		if($this->autoConnect)
			$this->setActive(true);
	}
	public function getActive()
	{
		return $this->_active;
	}
	public function setActive($value)
	{
		if($value!=$this->_active)
		{
			if($value)
				$this->open();
			else
				$this->close();
		}
	}
	protected function open()
	{
		if($this->_pdo===null)
		{
			if(empty($this->connectionString))
				throw new CDbException(Yii::t('yii','CDbConnection.connectionString cannot be empty.'));
			try
			{
				$this->_pdo=$this->createPdoInstance();
				$this->initConnection($this->_pdo);
				$this->_active=true;
			}
			catch(PDOException $e)
			{
				throw new CDbException(Yii::t('yii','CDbConnection failed to open the DB connection: {error}',
					array('{error}'=>$e->getMessage())));
			}
		}
	}
	protected function close()
	{
		$this->_pdo=null;
		$this->_active=false;
		$this->_schema=null;
	}
	protected function createPdoInstance()
	{
		$pdoClass='PDO';
		if(($pos=strpos($this->connectionString,':'))!==false)
		{
			$driver=strtolower(substr($this->connectionString,0,$pos));
			if($driver==='mssql' || $driver==='dblib')
				$pdoClass='CMssqlPdoAdapter';
		}
		return new $pdoClass($this->connectionString,$this->username,
									$this->password,$this->_attributes);
	}
	protected function initConnection($pdo)
	{
		$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
		if($this->emulatePrepare && constant('PDO::ATTR_EMULATE_PREPARES'))
			$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);
		if($this->charset!==null)
		{
			if(strcasecmp($pdo->getAttribute(PDO::ATTR_DRIVER_NAME),'sqlite'))
				$pdo->exec('SET NAMES '.$pdo->quote($this->charset));
		}
	}
	public function getPdoInstance()
	{
		return $this->_pdo;
	}
	public function createCommand($sql)
	{
		if($this->getActive())
			return new CDbCommand($this,$sql);
		else
			throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
	}
	public function getCurrentTransaction()
	{
		if($this->_transaction!==null)
		{
			if($this->_transaction->getActive())
				return $this->_transaction;
		}
		return null;
	}
	public function beginTransaction()
	{
		if($this->getActive())
		{
			$this->_pdo->beginTransaction();
			return $this->_transaction=new CDbTransaction($this);
		}
		else
			throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
	}
	public function getSchema()
	{
		if($this->_schema!==null)
			return $this->_schema;
		else
		{
			if(!$this->getActive())
				throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
			$driver=$this->getDriverName();
			switch(strtolower($driver))
			{
				case 'pgsql':  // PostgreSQL
					return $this->_schema=new CPgsqlSchema($this);
				case 'mysqli': // MySQL
				case 'mysql':
					return $this->_schema=new CMysqlSchema($this);
				case 'sqlite': // sqlite 3
				case 'sqlite2': // sqlite 2
					return $this->_schema=new CSqliteSchema($this);
				case 'mssql': // Mssql driver on windows hosts
				case 'dblib': // dblib drivers on linux (and maybe others os) hosts
					return $this->_schema=new CMssqlSchema($this);
				case 'oci':  // Oracle driver
					return $this->_schema=new COciSchema($this);
				case 'ibm':
				default:
					throw new CDbException(Yii::t('yii','CDbConnection does not support reading schema for {driver} database.',
						array('{driver}'=>$driver)));
			}
		}
	}
	public function getCommandBuilder()
	{
		return $this->getSchema()->getCommandBuilder();
	}
	public function getLastInsertID($sequenceName='')
	{
		if($this->getActive())
			return $this->_pdo->lastInsertId($sequenceName);
		else
			throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
	}
	public function quoteValue($str)
	{
		if($this->getActive())
			return $this->_pdo->quote($str);
		else
			throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
	}
	public function quoteTableName($name)
	{
		return $this->getSchema()->quoteTableName($name);
	}
	public function quoteColumnName($name)
	{
		return $this->getSchema()->quoteColumnName($name);
	}
	public function getPdoType($type)
	{
		static $map=array
		(
			'boolean'=>PDO::PARAM_BOOL,
			'integer'=>PDO::PARAM_INT,
			'string'=>PDO::PARAM_STR,
			'NULL'=>PDO::PARAM_NULL,
		);
		return isset($map[$type]) ? $map[$type] : PDO::PARAM_STR;
	}
	public function getColumnCase()
	{
		return $this->getAttribute(PDO::ATTR_CASE);
	}
	public function setColumnCase($value)
	{
		$this->setAttribute(PDO::ATTR_CASE,$value);
	}
	public function getNullConversion()
	{
		return $this->getAttribute(PDO::ATTR_ORACLE_NULLS);
	}
	public function setNullConversion($value)
	{
		$this->setAttribute(PDO::ATTR_ORACLE_NULLS,$value);
	}
	public function getAutoCommit()
	{
		return $this->getAttribute(PDO::ATTR_AUTOCOMMIT);
	}
	public function setAutoCommit($value)
	{
		$this->setAttribute(PDO::ATTR_AUTOCOMMIT,$value);
	}
	public function getPersistent()
	{
		return $this->getAttribute(PDO::ATTR_PERSISTENT);
	}
	public function setPersistent($value)
	{
		return $this->setAttribute(PDO::ATTR_PERSISTENT,$value);
	}
	public function getDriverName()
	{
		return $this->getAttribute(PDO::ATTR_DRIVER_NAME);
	}
	public function getClientVersion()
	{
		return $this->getAttribute(PDO::ATTR_CLIENT_VERSION);
	}
	public function getConnectionStatus()
	{
		return $this->getAttribute(PDO::ATTR_CONNECTION_STATUS);
	}
	public function getPrefetch()
	{
		return $this->getAttribute(PDO::ATTR_PREFETCH);
	}
	public function getServerInfo()
	{
		return $this->getAttribute(PDO::ATTR_SERVER_INFO);
	}
	public function getServerVersion()
	{
		return $this->getAttribute(PDO::ATTR_SERVER_VERSION);
	}
	public function getTimeout()
	{
		return $this->getAttribute(PDO::ATTR_TIMEOUT);
	}
	public function getAttribute($name)
	{
		if($this->getActive())
			return $this->_pdo->getAttribute($name);
		else
			throw new CDbException(Yii::t('yii','CDbConnection is inactive and cannot perform any DB operations.'));
	}
	public function setAttribute($name,$value)
	{
		if($this->_pdo instanceof PDO)
			$this->_pdo->setAttribute($name,$value);
		else
			$this->_attributes[$name]=$value;
	}
	public function getStats()
	{
		$logger=Yii::getLogger();
		$timings=$logger->getProfilingResults(null,'system.db.CDbCommand.query');
		$count=count($timings);
		$time=array_sum($timings);
		$timings=$logger->getProfilingResults(null,'system.db.CDbCommand.execute');
		$count+=count($timings);
		$time+=array_sum($timings);
		return array($count,$time);
	}
}
abstract class CDbSchema extends CComponent
{
	private $_tableNames=array();
	private $_tables=array();
	private $_connection;
	private $_builder;
	private $_cacheExclude=array();
	abstract protected function createTable($name);
	public function __construct($conn)
	{
		$conn->setActive(true);
		$this->_connection=$conn;
		foreach($conn->schemaCachingExclude as $name)
			$this->_cacheExclude[$name]=true;
	}
	public function getDbConnection()
	{
		return $this->_connection;
	}
	public function getTable($name)
	{
		if(isset($this->_tables[$name]))
			return $this->_tables[$name];
		else if(!isset($this->_cacheExclude[$name]) && ($duration=$this->_connection->schemaCachingDuration)>0 && $this->_connection->schemaCacheID!==false && ($cache=Yii::app()->getComponent($this->_connection->schemaCacheID))!==null)
		{
			$key='yii:dbschema'.$this->_connection->connectionString.':'.$this->_connection->username.':'.$name;
			if(($table=$cache->get($key))===false)
			{
				$table=$this->createTable($name);
				$cache->set($key,$table,$duration);
			}
			return $this->_tables[$name]=$table;
		}
		else
			return $this->_tables[$name]=$this->createTable($name);
	}
	public function getTables($schema='')
	{
		$tables=array();
		foreach($this->getTableNames($schema) as $name)
			$tables[$name]=$this->getTable($name);
		return $tables;
	}
	public function getTableNames($schema='')
	{
		if(!isset($this->_tableNames[$schema]))
			$this->_tableNames[$schema]=$this->findTableNames($schema);
		return $this->_tableNames[$schema];
	}
	public function getCommandBuilder()
	{
		if($this->_builder!==null)
			return $this->_builder;
		else
			return $this->_builder=$this->createCommandBuilder();
	}
	public function refresh()
	{
		if(($duration=$this->_connection->schemaCachingDuration)>0 && $this->_connection->schemaCacheID!==false && ($cache=Yii::app()->getComponent($this->_connection->schemaCacheID))!==null)
		{
			foreach(array_keys($this->_tables) as $name)
			{
				if(!isset($this->_cacheExclude[$name]))
				{
					$key='yii:dbschema'.$this->_connection->connectionString.':'.$this->_connection->username.':'.$name;
					$cache->delete($key);
				}
			}
		}
		$this->_tables=array();
		$this->_tableNames=array();
		$this->_builder=null;
	}
	public function quoteTableName($name)
	{
		return "'".$name."'";
	}
	public function quoteColumnName($name)
	{
		return '"'.$name.'"';
	}
	public function compareTableNames($name1,$name2)
	{
		$name1=str_replace(array('"','`',"'"),'',$name1);
		$name2=str_replace(array('"','`',"'"),'',$name2);
		if(($pos=strrpos($name1,'.'))!==false)
			$name1=substr($name1,$pos+1);
		if(($pos=strrpos($name2,'.'))!==false)
			$name2=substr($name2,$pos+1);
		return $name1===$name2;
	}
	protected function createCommandBuilder()
	{
		return new CDbCommandBuilder($this);
	}
	protected function findTableNames($schema='')
	{
		throw new CDbException(Yii::t('yii','{class} does not support fetching all table names.',
			array('{class}'=>get_class($this))));
	}
}
class CSqliteSchema extends CDbSchema
{
	protected function findTableNames($schema='')
	{
		$sql="SELECT DISTINCT tbl_name FROM sqlite_master WHERE tbl_name<>'sqlite_sequence'";
		return $this->getDbConnection()->createCommand($sql)->queryColumn();
	}
	protected function createCommandBuilder()
	{
		return new CSqliteCommandBuilder($this);
	}
	protected function createTable($name)
	{
		$db=$this->getDbConnection();
		$table=new CDbTableSchema;
		$table->name=$name;
		$table->rawName=$this->quoteTableName($name);
		if($this->findColumns($table))
		{
			$this->findConstraints($table);
			return $table;
		}
		else
			return null;
	}
	protected function findColumns($table)
	{
		$sql="PRAGMA table_info({$table->rawName})";
		$columns=$this->getDbConnection()->createCommand($sql)->queryAll();
		if(empty($columns))
			return false;
		foreach($columns as $column)
		{
			$c=$this->createColumn($column);
			$table->columns[$c->name]=$c;
			if($c->isPrimaryKey)
			{
				if($table->primaryKey===null)
					$table->primaryKey=$c->name;
				else if(is_string($table->primaryKey))
					$table->primaryKey=array($table->primaryKey,$c->name);
				else
					$table->primaryKey[]=$c->name;
			}
		}
		if(is_string($table->primaryKey) && !strncasecmp($table->columns[$table->primaryKey]->dbType,'int',3))
			$table->sequenceName='';
		return true;
	}
	protected function findConstraints($table)
	{
		$foreignKeys=array();
		$sql="PRAGMA foreign_key_list({$table->rawName})";
		$keys=$this->getDbConnection()->createCommand($sql)->queryAll();
		foreach($keys as $key)
		{
			$column=$table->columns[$key['from']];
			$column->isForeignKey=true;
			$foreignKeys[$key['from']]=array($key['table'],$key['to']);
		}
		$table->foreignKeys=$foreignKeys;
	}
	protected function createColumn($column)
	{
		$c=new CSqliteColumnSchema;
		$c->name=$column['name'];
		$c->rawName=$this->quoteColumnName($c->name);
		$c->allowNull=!$column['notnull'];
		$c->isPrimaryKey=$column['pk']!=0;
		$c->isForeignKey=false;
		$c->init(strtolower($column['type']),$column['dflt_value']);
		return $c;
	}
}
class CDbTableSchema extends CComponent
{
	public $name;
	public $rawName;
	public $primaryKey;
	public $sequenceName;
	public $foreignKeys=array();
	public $columns=array();
	public function getColumn($name)
	{
		return isset($this->columns[$name]) ? $this->columns[$name] : null;
	}
	public function getColumnNames()
	{
		return array_keys($this->columns);
	}
}
class CDbCommand extends CComponent
{
	private $_connection;
	private $_text='';
	private $_statement=null;
	private $_params=array();
	public function __construct(CDbConnection $connection,$text)
	{
		$this->_connection=$connection;
		$this->setText($text);
	}
	public function __sleep()
	{
		$this->_statement=null;
		return array_keys(get_object_vars($this));
	}
	public function getText()
	{
		return $this->_text;
	}
	public function setText($value)
	{
		$this->_text=$value;
		$this->cancel();
	}
	public function getConnection()
	{
		return $this->_connection;
	}
	public function getPdoStatement()
	{
		return $this->_statement;
	}
	public function prepare()
	{
		if($this->_statement==null)
		{
			try
			{
				$this->_statement=$this->getConnection()->getPdoInstance()->prepare($this->getText());
				$this->_params=array();
			}
			catch(Exception $e)
			{
				Yii::log('Error in preparing SQL: '.$this->getText(),CLogger::LEVEL_ERROR,'system.db.CDbCommand');
				throw new CDbException(Yii::t('yii','CDbCommand failed to prepare the SQL statement: {error}',
					array('{error}'=>$e->getMessage())));
			}
		}
	}
	public function cancel()
	{
		$this->_statement=null;
	}
	public function bindParam($name, &$value, $dataType=null, $length=null)
	{
		$this->prepare();
		if($dataType===null)
			$this->_statement->bindParam($name,$value,$this->_connection->getPdoType(gettype($value)));
		else if($length===null)
			$this->_statement->bindParam($name,$value,$dataType);
		else
			$this->_statement->bindParam($name,$value,$dataType,$length);
		if($this->_connection->enableParamLogging)
			$this->_params[$name]='['.gettype($value).']';
		return $this;
	}
	public function bindValue($name, $value, $dataType=null)
	{
		$this->prepare();
		if($dataType===null)
			$this->_statement->bindValue($name,$value,$this->_connection->getPdoType(gettype($value)));
		else
			$this->_statement->bindValue($name,$value,$dataType);
		if($this->_connection->enableParamLogging)
			$this->_params[$name]=var_export($value,true);
		return $this;
	}
	public function execute($params=array())
	{
		if($this->_connection->enableParamLogging && ($pars=array_merge($this->_params,$params))!==array())
		{
			foreach($pars as $name=>$value)
				$pars[$name]=$name.'='.$value;
			$par='. Bind with parameter ' .implode(', ',$pars);
		}
		else
			$par='';
		try
		{
			if($this->_connection->enableProfiling)
				Yii::beginProfile('system.db.CDbCommand.execute('.$this->getText().')','system.db.CDbCommand.execute');
			$this->prepare();
			$this->_statement->execute($params===array() ? null : $params);
			$n=$this->_statement->rowCount();
			if($this->_connection->enableProfiling)
				Yii::endProfile('system.db.CDbCommand.execute('.$this->getText().')','system.db.CDbCommand.execute');
			return $n;
		}
		catch(Exception $e)
		{
			if($this->_connection->enableProfiling)
				Yii::endProfile('system.db.CDbCommand.execute('.$this->getText().')','system.db.CDbCommand.execute');
			Yii::log('Error in executing SQL: '.$this->getText().$par,CLogger::LEVEL_ERROR,'system.db.CDbCommand');
			throw new CDbException(Yii::t('yii','CDbCommand failed to execute the SQL statement: {error}'.$this->text,
				array('{error}'=>$e->getMessage())));
		}
	}
	public function query($params=array())
	{
		return $this->queryInternal('',0,$params);
	}
	public function queryAll($fetchAssociative=true,$params=array())
	{
		return $this->queryInternal('fetchAll',$fetchAssociative ? PDO::FETCH_ASSOC : PDO::FETCH_NUM, $params);
	}
	public function queryRow($fetchAssociative=true,$params=array())
	{
		return $this->queryInternal('fetch',$fetchAssociative ? PDO::FETCH_ASSOC : PDO::FETCH_NUM, $params);
	}
	public function queryScalar($params=array())
	{
		$result=$this->queryInternal('fetchColumn',0,$params);
		if(is_resource($result) && get_resource_type($result)==='stream')
			return stream_get_contents($result);
		else
			return $result;
	}
	public function queryColumn($params=array())
	{
		return $this->queryInternal('fetchAll',PDO::FETCH_COLUMN,$params);
	}
	private function queryInternal($method,$mode,$params=array())
	{
		if($this->_connection->enableParamLogging && ($pars=array_merge($this->_params,$params))!==array())
		{
			foreach($pars as $name=>$value)
				$pars[$name]=$name.'='.$value;
			$par='. Bind with parameter ' .implode(', ',$pars);
		}
		else
			$par='';
		try
		{
			if($this->_connection->enableProfiling)
				Yii::beginProfile('system.db.CDbCommand.query('.$this->getText().')','system.db.CDbCommand.query');
			$this->prepare();
			$this->_statement->execute($params===array() ? null : $params);
			if($method==='')
				$result=new CDbDataReader($this);
			else
			{
				$result=$this->_statement->{$method}($mode);
				$this->_statement->closeCursor();
			}
			if($this->_connection->enableProfiling)
				Yii::endProfile('system.db.CDbCommand.query('.$this->getText().')','system.db.CDbCommand.query');
			return $result;
		}
		catch(Exception $e)
		{
			if($this->_connection->enableProfiling)
				Yii::endProfile('system.db.CDbCommand.query('.$this->getText().')','system.db.CDbCommand.query');
			Yii::log('Error in querying SQL: '.$this->getText().$par,CLogger::LEVEL_ERROR,'system.db.CDbCommand');
			throw new CDbException(Yii::t('yii','CDbCommand failed to execute the SQL statement: {error}',
				array('{error}'=>$e->getMessage())));
		}
	}
}
class CDbColumnSchema extends CComponent
{
	public $name;
	public $rawName;
	public $allowNull;
	public $dbType;
	public $type;
	public $defaultValue;
	public $size;
	public $precision;
	public $scale;
	public $isPrimaryKey;
	public $isForeignKey;
	public function init($dbType, $defaultValue)
	{
		$this->dbType=$dbType;
		$this->extractType($dbType);
		$this->extractLimit($dbType);
		if($defaultValue!==null)
			$this->extractDefault($defaultValue);
	}
	protected function extractType($dbType)
	{
		if(stripos($dbType,'int')!==false)
			$this->type='integer';
		else if(stripos($dbType,'bool')!==false)
			$this->type='boolean';
		else if(preg_match('/(real|floa|doub)/i',$dbType))
			$this->type='double';
		else
			$this->type='string';
	}
	protected function extractLimit($dbType)
	{
		if(strpos($dbType,'(') && preg_match('/\((.*)\)/',$dbType,$matches))
		{
			$values=explode(',',$matches[1]);
			$this->size=$this->precision=(int)$values[0];
			if(isset($values[1]))
				$this->scale=(int)$values[1];
		}
	}
	protected function extractDefault($defaultValue)
	{
		$this->defaultValue=$this->typecast($defaultValue);
	}
	public function typecast($value)
	{
		if(gettype($value)===$this->type || $value===null || $value instanceof CDbExpression)
			return $value;
		if($value==='')
			return $this->type==='string' ? '' : null;
		switch($this->type)
		{
			case 'integer': return (integer)$value;
			case 'boolean': return (boolean)$value;
			case 'double': return (double)$value;
			case 'string': return (string)$value;
			default: return $value;
		}
	}
}
class CSqliteColumnSchema extends CDbColumnSchema
{
	protected function extractDefault($defaultValue)
	{
		if($this->type==='string') // PHP 5.2.6 adds single quotes while 5.2.0 doesn't
			$this->defaultValue=trim($defaultValue,"'\"");
		else
			$this->defaultValue=$this->typecast($defaultValue);
	}
}
interface IApplicationComponent
{
	public function init();
	public function getIsInitialized();
}
interface ICache
{
	public function get($id);
	public function mget($ids);
	public function set($id,$value,$expire=0,$dependency=null);
	public function add($id,$value,$expire=0,$dependency=null);
	public function delete($id);
	public function flush();
}
interface ICacheDependency
{
	public function evaluateDependency();
	public function getHasChanged();
}
interface IStatePersister
{
	public function load();
	public function save($state);
}
interface IFilter
{
	public function filter($filterChain);
}
interface IAction
{
	public function run();
	public function getId();
	public function getController();
}
interface IWebServiceProvider
{
	public function beforeWebMethod($service);
	public function afterWebMethod($service);
}
interface IViewRenderer
{
	public function renderFile($context,$file,$data,$return);
}
interface IUserIdentity
{
	public function authenticate();
	public function getIsAuthenticated();
	public function getId();
	public function getName();
	public function getPersistentStates();
}
interface IWebUser
{
	public function getId();
	public function getName();
	public function getIsGuest();
	public function checkAccess($operation,$params=array());
}
interface IAuthManager
{
	public function checkAccess($itemName,$userId,$params=array());
	public function createAuthItem($name,$type,$description='',$bizRule=null,$data=null);
	public function removeAuthItem($name);
	public function getAuthItems($type=null,$userId=null);
	public function getAuthItem($name);
	public function saveAuthItem($item,$oldName=null);
	public function addItemChild($itemName,$childName);
	public function removeItemChild($itemName,$childName);
	public function hasItemChild($itemName,$childName);
	public function getItemChildren($itemName);
	public function assign($itemName,$userId,$bizRule=null,$data=null);
	public function revoke($itemName,$userId);
	public function isAssigned($itemName,$userId);
	public function getAuthAssignment($itemName,$userId);
	public function getAuthAssignments($userId);
	public function saveAuthAssignment($assignment);
	public function clearAll();
	public function clearAuthAssignments();
	public function save();
	public function executeBizRule($bizRule,$params,$data);
}
interface IBehavior
{
	public function attach($component);
	public function detach($component);
	public function getEnabled();
	public function setEnabled($value);
}
?>